ngModel 无法正确检测数组更改 [英] ngModel cannot detect array changes correctly
问题描述
组件模型:
private SomeArray = [{ key: "Initial" }];
用户可以动态添加/删除项目:
addField() {this.SomeArray.push({ key: Math.random().toString() });}removeField(索引:数字){this.SomeArray.splice(index, 1);}
模板标记:
<button (click)="addField()" type="button">添加</button><div *ngFor="let 字段 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">必需的错误
<button (click)="removeField(i)" class="btn btn-danger">Remove</button>
这一直有效,直到用户从 SomeArray
中删除任何项目.如果我最初添加了两个项目:
并删除索引为 1 的那个:
然后在添加另一个项目后,Angular 将其视为项目同时具有 0 和 1 索引(新项目占用"两个输入):
(不显示键为 0.1345... 的项目)
值得注意的是,SomeArray
的项目符合预期,但数据绑定失败.可能是什么原因?
更新:感谢@Stefan Svrkota 和@AJT_82 的评论,我知道这个问题可以通过添加[ngModelOptions]="{standalone: true}"代码> 到所需的输入.但是我无法停止思考问题的原因,没有设置
standalone
选项(每个名称属性都有唯一的值,所以这里没有任何错误).
最后我发现当输入元素仅进入 标签时会发生行为 -
2) Step2 - SomeArray[1].key
已从 controls
集合中移除
3) Step3 - Html 看起来像
4) Step4 我们正在添加一个新项目
所以 formGroup
返回现有项目.
我们如何解决?
1) 不要将我们的控件包裹在 form
标签中
2) 给表单添加ngNoForm
属性
3) 使用
[ngModelOptions]="{standalone: true}
以上三种解决方案:
我们可以移除
[name]
属性绑定我们不能使用内置的表单组验证
4) 将 trackBy 用于 ngFor
template.html
component.ts
trackByFn(i: number) {返回我;}
这样我们的内置表单就可以正常工作
The component model:
private SomeArray = [{ key: "Initial" }];
User can add/remove items dynamically:
addField() {
this.SomeArray.push({ key: Math.random().toString() });
}
removeField(index: number) {
this.SomeArray.splice(index, 1);
}
Template markup:
<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>
This works untill user removes any item from SomeArray
. If I add some two items initially:
and remove the one with 1 index:
then after adding another item Angular treat it as item has both 0 and 1 index (the new item "occupies" both two inputs):
(item with key 0.1345... is not displayed)
It's worth to noting items of SomeArray
are as expected, but data binding fails. What can be the reason of it?
Update: Thanks to the comments of @Stefan Svrkota and @AJT_82 it's known for me the issue can be resolved by adding [ngModelOptions]="{standalone: true}"
to the needed input. But I couldn't stop thinking about the reason of the issue in my cause, without setting standalone
option (there is unique value for each name attribute so it's excepted nothing wrong here).
Finally I have found that behavior occurs when input elements are into <form>
tag only - Plunker sample here (enclosing of template with form tag is the reason that issue).
Any ideas of this behavior?
解决方案 The reason why it happens is ngFor
mixes name
properties when you delete some item.
When you use ngModel
inside form
each ngModel
control will be added to form controls collection.
Let's see what happens if we have added three items and clicked on Remove
the second
1) Step1 - SomeArray[1].key
exists in collection controls
2) Step2 - SomeArray[1].key
has been removed from controls
collection
3) Step3 - Html looks like
4) Step4 We are adding a new item
So formGroup
returns existing item.
How we can solve it?
1) Don't wrap our controls in form
tag
2) Add ngNoForm
attribute to form
<form ngNoForm>
3) Use
[ngModelOptions]="{standalone: true}
With all three solutions above:
We can remove [name]
property binding
We can't use the built in Form group validation
4) Use trackBy for ngFor
template.html
<div *ngFor="let field of SomeArray; let i = index; trackBy: trackByFn">
component.ts
trackByFn(i: number) {
return i;
}
This way our built in form will work properly
这篇关于ngModel 无法正确检测数组更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文