我正在尝试为地址集合创建一个简单的组件。用户可以添加,删除和编辑所有地址。除了存在多个地址外,用户只删除第一个地址,然后添加新地址。添加了新地址,但也清除了现有地址。在我的应用程序中,我也得到错误 - 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);
}
}
&#13;
答案 0 :(得分:2)
我能够通过使用ngFor的trackBy功能来完成工作。这是修改后的代码,也对StackBlitz进行了修正。
@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);
}
}
答案 1 :(得分:0)
你想要一个FormArray
。它非常适合这种事情。我已经继续使用Reactive Forms重新创建您的应用程序,因此您可以比较和对比,看看它是如何工作的。
以下是包含所有代码的工作示例的链接:https://stackblitz.com/edit/angular-eeamqq。
请注意,我将反应形式的值添加到模板中,因此您可以看到它本质上是一个动态构建的对象。
如果您希望我进一步扩展我在上述应用中使用的一些技术,请告诉我。
我还会在这里链接代码,以便您可以在不加载应用程序的情况下查看它:
模板:
<button type="button" (click)="onAdd()">Add</button>
<hr>
<form [formGroup]="addressForm">
<div formArrayName="addresses"
*ngFor="let address of addressForm.get('addresses').controls; let i = index;">
<div [formGroupName]="i">
<input formControlName="address1" placeholder="Address 1">
<input formControlName="address2" placeholder="Address 2">
<input formControlName="city" placeholder="City">
<input formControlName="state" placeholder="State">
<input formControlName="zip" placeholder="Zip">
<button (click)="onDelete(i)">Delete</button>
</div>
<hr>
</div>
</form>
组件类的重要部分:
constructor(private fb: FormBuilder) {}
ngOnInit() {
const addressForms = this.data.map(address => this.createAddressForm(address));
this.addressForm = this.fb.group({
addresses: this.fb.array(addressForms)
});
}
createAddressGroup(address?: any) {
return this.fb.group({
address1: address ? address.address1 : '',
address2: address ? address.address2 : '',
city: address ? address.city : '',
state: address ? address.state : '',
zip: address ? address.zip : ''
});
}
onAdd() {
const addresses = this.addressForm.get('addresses') as FormArray;
addresses.push(this.createAddressForm());
}
onDelete(index: number) {
const addresses = this.addressForm.get('addresses') as FormArray;
addresses.removeAt(index);
}