以下代码将生成两个具有相同值inputs
的{{1}}(而不是bye
和hello
)。如果有人能够(理论上)解释这种行为并指出确切原因,那将是很好的。
bye
编辑:为了更好地解释我的问题:
原因可能不是因为它们绑定到同一对象,所以它们将具有相同的值。如果是这样,则以下情况对于两个输入都具有相同的值,显然不是这种情况。
app.component.html
<form>
<div *ngFor="let item of ['hello', 'bye'];">
<input name="name" [(ngModel)]="item">
</div>
</form>
app.component.ts
<form>
<div *ngFor="let item of arr;">
<input name="name" [(ngModel)]="item">
</div>
</form>
请注意::我想我已经正确解释了我的问题,以及为什么我认为@DeborahK的解决方案似乎不适合我。我正在寻找这种行为的原因。而不是解决方法。另外,我知道在每个输入中更改 arr = [1,4]
ngOnInit(){
setTimeout(()=>{
this.arr[1] = 5;
});
}
可以使其正常工作。因此,请不要再建议了。
答案 0 :(得分:3)
名称属性应唯一
<form>
<div *ngFor="let item of ['hello', 'bye'];let i =index">
<input name="{{i}}" [(ngModel)]="item">
</div>
</form>
答案 1 :(得分:0)
以下是有关此处答案为何要使用唯一名称的进一步说明。而且此解决方案不是 的解决方法。这只是工作方式。
当使用模板驱动的表单时(即使用ngModel
时),Angular会自动构建一个数据结构来保存所有表单信息。这包括状态信息(脏污,被触摸等)和表单值。它根据“控制名称”保存此信息!
因此,如果您的名字相同,则它们在数据结构中的位置为“一个元素”,因此不能有两个值。
如果您为表单定义模板引用变量,则可以自己查看此数据结构:
<form #myForm="ngForm">
<div *ngFor="let item of ['hello', 'bye'];">
<input name="name" [(ngModel)]="item">
</div>
<div>{{ myForm.value | json }}</div>
</form>
我刚刚进行了一次堆栈闪电演示,以演示您的数组示例,以表明它仍然只是一个具有一个值的元素:
答案 2 :(得分:0)
您的code sample中似乎有两个问题的组合:
为说明最后一点,您可以通过在代码中修改两个输入来强制在更改检测时重新创建两个输入:
changeValues() {
this.arr[0] = 2;
this.arr[1] = 3;
}
您可以在this stackblitz中看到更新后两个输入的内容相同。
可以借助ngFor
方法来防止trackBy
循环中绑定输入元素的破坏/创建,该方法可以通过索引来跟踪数组元素,而不是通过值来跟踪数组元素。您可以在this stackblitz中看到两个输入元素正确共享同一FormControl。
<div *ngFor="let item of arr; trackBy: trackByFn">
<input name="name" [ngModel]="item">
</div>
trackByFn(index, value) {
return index;
}
最后,只需对原始代码进行3次更改即可获得正确的行为:
trackBy
方法(按索引)防止输入元素的破坏/创建item
<div *ngFor="let item of arr; let i = index; trackBy: trackByFn">
<input name="name_{{i}}" [(ngModel)]="arr[i]">
</div>
trackByFn(index, value) {
return index;
}
您可以查看this stackblitz进行演示。
通过调用ngModel
修改绑定数据时,FormControl
指令updates FormControl.setValue
:
ngOnChanges(changes: SimpleChanges) {
...
if (isPropertyUpdated(changes, this.viewModel)) {
this._updateValue(this.model);
this.viewModel = this.model;
}
}
private _updateValue(value: any): void {
resolvedPromise.then(
() => { this.control.setValue(value, {emitViewToModelChange: false}); });
}
您会看到FormControl.patchValue
也呼叫setValue
:
patchValue(value: any, options: {
onlySelf?: boolean,
emitEvent?: boolean,
emitModelToViewChange?: boolean,
emitViewToModelChange?: boolean
} = {}): void {
this.setValue(value, options);
}