Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ngFor shows empty items after array.push

Tags:

angular

ngfor

I have this in my template:

<input type="button" value="add" (click)="addEnvVar()"/>
<div *ngFor="let envVar of application.env_vars">
    <input type="text" name="key" [(ngModel)]="envVar.key">
    <input type="text" name="value" [(ngModel)]="envVar.value">
</div>

The code behind addEnvVar(): this.application.env_vars.push({key:'', value:''});

When the component is initialized, there is one object inside env_vars and it is rendered just fine (the <input> fields are populated). After I click 'add', I can see in console that there are indeed two objects inside env_vars (the second is the 'empty' object I just added), and in the view there are indeed two <div>s for each envVar, but all 4 <input> fields are empty.

What am I doing wrong?

UPDATE

I think the problem is that when ngFor produces more than one div, the inputs in each div all get the same hard-coded name attribute (in my case - "key" and "value"), and the value is somehow attached to that. I changed name="key" to name="key_{{i}}" (i is a template variable holding the ngFor index property).

Question is, is this the way to go? Or am I still missing something?

like image 914
OzW Avatar asked Oct 31 '16 10:10

OzW


1 Answers

The culprit with errors like this is mostly likely the default trackBy function which tracks the references. Even if the data hasn't changed, but the references change, it will tear down the DOM and re-build it, meaning all data inside the input fields will be cleared.

Component

trackBy(index) { return index }

Template

*ngFor="let envVar of application.env_vars; trackBy: trackBy"

Unfortunately I cannot test it without a reproduction. However, JB Nizet's comment is right and you should follow this advice; this is a task more suited for reactive forms, and not template forms.

like image 178
Lazar Ljubenović Avatar answered Oct 19 '22 05:10

Lazar Ljubenović