StackBlitzExample
I am trying to create a simple component for a collection of addresses. The user can add, remove, and edit all of the addresses. It all mostly works except when there exists more than one address, the user deletes the first address only, and then adds a new address. The new address is added but the existing address is also cleared. In my application I also get the error - ExpressionChangedAfterItHasBeenCheckedError.
import { Component, Input } from '@angular/core';
@Component({
selector: 'hello',
template: `<h1>Hello {{name}}!</h1><button type="button" (click)="add()">Add</button>
<form>
<div *ngFor="let addr of data; let i=index;">
<input name="{{'address1'+i}}" type="text" [(ngModel)]="addr.address1" />
<input name="{{'zip'+i}}" type="text" [(ngModel)]="addr.zip" />
<button type="button" (click)="delete(i, addr)">Delete</button>
<hr/>
</div>
</form>
`,
styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent {
@Input() name: string;
data = [
{
address1:'500 Main St',
address2:'',
city:'Norman',
state:'OK',
zip:'73070'
},
{
address1:'501 Main St',
address2:'',
city:'OKC',
state:'OK',
zip:'73105'
}
];
add() {
this.data.push( { address1:'',
address2:'',
city:'',
state:'',
zip:''});
}
delete(index:number, row:any) {
this.data.splice(index, 1);
}
}
I was able to get things to work by using the trackBy feature of ngFor. Here is the modified code and the correction was made to StackBlitz also.
@Component({
selector: 'hello',
template: `<h1>Hello {{name}}!</h1><button type="button" (click)="add()">Add</button>
<form>
<div *ngFor="let addr of data; let i=index; trackBy:trackByIndex">
<input name="{{'address1'+i}}" type="text" [(ngModel)]="addr.address1" />
<input name="{{'address2'+i}}" type="text" [(ngModel)]="addr.address2" />
<input name="{{'city'+i}}" type="text" [(ngModel)]="addr.city" />
<input name="{{'state'+i}}" type="text" [(ngModel)]="addr.state" />
<input name="{{'zip'+i}}" type="text" [(ngModel)]="addr.zip" />
<button type="button" (click)="delete(i, addr)">Delete</button>
<hr/>
</div>
</form>
`,
styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent {
@Input() name: string;
data = [
{
address1:'500 Main St',
address2:'',
city:'Norman',
state:'OK',
zip:'73070'
},
{
address1:'501 Main St',
address2:'',
city:'OKC',
state:'OK',
zip:'73105'
}
];
add() {
this.data.push( { address1:'',
address2:'',
city:'',
state:'',
zip:''});
}
public trackByIndex(index: number, value: number) {
return index;
}
delete(index:number, row:any) {
this.data.splice(index, 1);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With