ngModel无法正确检测阵列更改

时间:2017-06-10 18:24:57

标签: javascript angular angular2-template

组件模型:

private SomeArray = [{ key: "Initial" }];

用户可以动态添加/删除项目:

addField() {
    this.SomeArray.push({ key: Math.random().toString() });
}

removeField(index: number) {
    this.SomeArray.splice(index, 1);
}

模板标记:

 <div class="col-xs-12">
     <button (click)="addField()" type="button">Add</button>
 </div>

 <div *ngFor="let field of SomeArray; let i = index;">
     <input [(ngModel)]="field.key" #modelField="ngModel" [name]=" 'SomeArray['+i+'].key' " type="text" class="form-control" required />
     <div [hidden]="modelField.pristine || !(modelField.errors && modelField.errors.required)" class="alert alert-danger">
        Required error
     </div>

    <button (click)="removeField(i)" class="btn btn-danger">Remove</button>
 </div>

这样可以直到SomeArray删除任何项目。如果我最初添加两个项目: enter image description here

并删除1索引:

enter image description here

然后添加另一个项目Angular将其视为具有0和1索引的项目(新项目&#34;占用&#34;两个输入):

enter image description here

(带有键0.1345的项目...不显示)

值得注意SomeArray的项目符合预期,但数据绑定失败。可能是什么原因?

更新:感谢@Stefan Svrkota和@ AJT_82的评论,我知道这个问题可以通过在所需输入中添加[ngModelOptions]="{standalone: true}"来解决。但是,如果不设置standalone选项(每个名称属性都有唯一的值,因此它在这里除外没有任何错误),我无法在我的事业中停止思考问题的原因。

最后,我发现当输入元素仅进入<form>标记时会发生这种行为 - Plunker sample here(带有表单标记的模板的封闭是问题的原因)。

有关此行为的任何想法吗?

1 个答案:

答案 0 :(得分:5)

当您删除某个项目时,ngFor混合name属性的原因就在于此。

当您在ngModel内使用form时,每个ngModel控件都会添加到表单控件集合中。

让我们看看如果我们添加了三个项目并点击了Remove第二个

会发生什么

1)第1步 - SomeArray[1].key存在于集合controlsCross-site scripting

2)第2步 - SomeArray[1].key已从controls集合

中删除

enter image description here

3)Step3 - Html看起来像

enter image description here

4)Step4我们正在添加一个新项目

enter image description here

因此formGroup会返回现有项目。

我们如何解决它?

1)不要将我们的控件包装在form标签

2)将ngNoForm属性添加到表单

<form ngNoForm>

3)使用

[ngModelOptions]="{standalone: true}

以上三种解决方案:

  • 我们可以删除[name]属性绑定

  • 我们无法使用内置的表单组验证

4) 使用trackBy for ngFor

<强> template.html

<div *ngFor="let field of SomeArray; let i = index; trackBy: trackByFn">

<强> component.ts

trackByFn(i: number) {
  return i;
}

<强> enter image description here

这样我们的内置表单就能正常工作