Angular 2 - 具有可编辑输入的 ngFor 对象数组的双向绑定

Angular 2 - two way binding for ngFor objects array with editable inputs

我是 Angular 2 的新手,正在尝试实现具有可编辑输入的 ngFor 对象列表,能够添加新对象并保存数据。 数据为:

business: { email: "email@something.com", 
locations: [
{ country: "US", city: "city 1", address_line_1: "address 1"},
{ country: "Australia", city: "city 1", address_line_1: "address 2"}
]}

在组件中:

ngOnInit() {
this.businessForm = new FormGroup({
        email: new FormControl(null, [Validators.required]), 
        locationCountry: new FormControl(null)
});
addLocation() {
    this.isFormChanged = true;
    let newLocation = {};
    this.business.locations.push(newLocation);
}

removeLocation(item){
    if (null !== item) {
        this.isFormChanged = true;
        this.business.locations.splice(item, 1);
    }
}

Html:

<div class="form-group">
            <label for="locations">Locations</label>
            <div class="row">
                <div class="col-md-3">
                <button
                        id="locations"
                        class="btn btn-secondary"
                        type="button"
                        (click)="addLocation()">Add new address</button>

                </div>
            </div>

            <!--LOCATIONS LIST-->
            <ul class="locations-tag">
                <li *ngFor="let location of business?.locations; let index=index;">
                    <a class="btn btn-danger categories-tag-btn" (click)="removeLocation(index)">X</a>
                    <span>{{business?.locations[index].country}}</span>
                    <input
                            id="locations-{{index}}"
                            [(ngModel)]="business?.locations[index].country"
                            formControlName="locationCountry"
                            name="locations-{{index}}"
                            type="text" 
                            class="form-control"
                            placeholder="Country" 
                            aria-label="Country"
                            value={{business?.locations[index].country}}>
                    ...

                </li>
            </ul>

    </div>

运行时出现错误

ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'US'. Current value: 'Australia'.

看起来它将所有输入值更改为最后一个。 我试图通过 FormBuilder 实现同样的想法,但也没有成功。

我创建了一个 Plunker。我删除了 formControlName,因为它不是 FormsModule,它是 ReactiveFormsModule - 这是不同的。

有关 FormsModule(NgModel) vs ReactiveFormsModule 之间的更多信息,请阅读文档。此外,最好删除 value,因为您使用的 [(ngModel)] 正在对值进行双向数据绑定。

  <input
                        id="locations-{{index}}"
                        [(ngModel)]="business?.locations[index].country"
                        name="locations-{{index}}"
                        type="text" 
                        class="form-control"
                        placeholder="Country" 
                        aria-label="Country"
                        >

(回答因为我还没有被允许发表评论)。除了@alexKhymenko 的回答之外,如果您想坚持使用 ReactiveForms(Module),则必须将您在组件中创建的父级 formGroupbusinessForm 添加到模板中。虽然不确定这是否会解决您的问题,但请尝试将此属性添加到模板的顶部 <div class="form-group">,例如 <div class="form-group" [formGroup]="businessForm">。如果您对非反应式表单感到满意,那么@alexKhymenko 的回答可能就足够了。