Reputation: 11888
Here is my template :
<div *ngFor="let d of data; let i=index">
<select [(ngModel)]="d.dob" name="dob-{{i}}">
<option *ngFor="let d of [1990, 1991, 1992]">
{{d}}
</option>
</select>
<i class="fa fa-times" (click)="remove(i)"></i>
</div>
<button type="button"
class="btn btn-primary"
(click)="add()"
> + </button>
here is my component:
data: any[] = []
add(): void {
this.data.push({dob: undefined})
}
remove(index: number): void {
this.data.splice(index, 1)
}
For some reasons, when I have 2 selects, then start removing the first one, and add a new one, the value in the first one (which was the second at first) disapears.
It seems I should retrigger a rendering as the template is getting confused by the reference. I managed to get rid of the issue by addding
this.data= _.cloneDeep(this.data)
in my add
function
Any cleaner way to fix this issue ?
Upvotes: 1
Views: 2555
Reputation: 28708
Use trackBy
option on *ngFor
when the items are dynamically added or removed.
HTML
<div *ngFor="let d of data; let i=index; trackBy: trackByFn">
Typescript:
trackByFn(index, item) {
return index;
}
When the contents of the iterator changes, NgForOf makes the corresponding changes to the DOM:
When an item is added, a new instance of the template is added to the DOM. When an item is removed, its template instance is removed from the DOM. .... Otherwise, the DOM element for that item will remain the same. Angular uses object identity to track insertions and deletions within the iterator and reproduce those changes in the DOM.
To customize the default tracking algorithm, NgForOf supports trackBy option. trackBy takes a function which has two arguments: index and item. If trackBy is given, Angular tracks changes by the return value of the function.
Upvotes: 4