2017-06-10 29 views
1

组件模型:ngModel不能检测阵列的变化正确地

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

然后添加其他项目角治疗后,作为项目有0和1指数(新项目 “占用” 两两路输入):

enter image description here

(与关键0.1345项...未显示)

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

更新:感谢@Stefan Svrkota的评论和@ AJT_82它被称为我的问题可以通过添加[ngModelOptions]="{standalone: true}"到所需要的输入来解决。但我不能停止思考我的原因,没有设置standalone选项(每个名称属性都有一个唯一的值,所以在这里没有任何问题)。

最后,我发现当输入元素只输入<form>标签时发生该行为 - Plunker sample here(包含带表单标签的模板是导致问题的原因)。

这种行为的任何想法?

+1

https://stackoverflow.com/questions/41265761/using-ngfor-with -ngmodel-dynamic-data-wrong-behavior –

+0

@Stefan Svrkota解决了,谢谢) – Mergasov

+0

@ AJT_82我认为'[name] =''SomeArray ['+ i +'] .key'“'返回唯一的名称值迭代我)?我错了吗? – Mergasov

回答

2

它发生的原因是ngFor混合name属性,当你删除一些项目。

当你在form里面使用ngModel时每个ngModel控件都会被加入来形成控件集合。

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

1)第一步会发生什么 - SomeArray[1].key存在于收集controls enter image description here

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

enter image description here

3)第三步 - HTML如下

enter image description here

4)第四步:我们正在增加新的项目

enter image description here

所以formGroup回报现有项目。

我们如何解决它?

1)不要在包装标签form

2)添加ngNoForm属性我们的控制,形成

<form ngNoForm> 

3)使用

[ngModelOptions]="{standalone: true} 

与所有三个解决方案上面:

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

  • 我们不能使用内置的表格组生效

4)使用trackBy为ngFor

template.html

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

component.ts

trackByFn(i: number) { 
    return i; 
} 

Plunker Example

这样,我们的建筑形式将正常工作