简体   繁体   English

Angular 2-具有可编辑输入的ngFor对象数组的两种方式绑定

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

I'm new to Angular 2, trying to implement ngFor list of objects with editable inputs, be able to add a new object and save the data. 我是Angular 2的新手,尝试实现ngFor具有可编辑输入的对象列表,能够添加新对象并保存数据。 The data is: 数据为:

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"}
]}

In the component: 在组件中:

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: 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>

When it runs I get an error 它运行时出现错误

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

Looks like it changes all the inputs values to the last one. 看起来它将所有输入值更改为最后一个。 I tried to implement the same idea through FormBuilder, but it didn't work out either. 我试图通过FormBuilder实现相同的想法,但也没有奏效。

I have created a Plunker . 我创建了一个Plunker I remove formControlName because it's not FormsModule, it's ReactiveFormsModule - that is different. 我删除formControlName,因为它不是FormsModule,而是ReactiveFormsModule-有所不同。

For more information between FormsModule(NgModel) vs ReactiveFormsModule read documentation. 有关FormsModule(NgModel)ReactiveFormsModule之间的更多信息, 阅读文档。 Also, it's better to delete value because you are using [(ngModel)] that is making two-way data-binding to the value. 另外,最好删除值,因为您正在使用[(ngModel)]对值进行双向数据绑定。

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

(Answering since I am not yet allowed to comment). (正在回答,因为我尚未发表评论)。 In addition to @alexKhymenko's answer, if you want to stick with ReactiveForms(Module), you will have to add the parent formGroup , businessForm you created in your component, also to the template. 除了@alexKhymenko的答案外,如果您想坚持使用ReactiveForms(Module),还必须将在组件中创建的父formGroupbusinessForm都添加到模板中。 Not sure if this will fix your issue though, but try to add this attribute to the top <div class="form-group"> like this <div class="form-group" [formGroup]="businessForm"> of the template. 不知道这是否能解决您的问题,但是请尝试将此属性添加到顶部的<div class="form-group">这样的<div class="form-group" [formGroup]="businessForm">模板。 If you are happy with non-reactive forms, then @alexKhymenko's answer might be sufficient. 如果您对非反应性表单感到满意,那么@alexKhymenko的答案可能就足够了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM