Angular 2 - NgFor 中与 NgModel 的 2 路绑定
Posted
技术标签:
【中文标题】Angular 2 - NgFor 中与 NgModel 的 2 路绑定【英文标题】:Angular 2 - 2 Way Binding with NgModel in NgFor 【发布时间】:2017-03-11 21:59:01 【问题描述】:在 Angular 2 中,我如何使用 NgFor 在重复列表中与 NgModel 进行 2 路绑定。以下是我的 plunkr 和代码,但出现错误。
Plunkr
@Component(
selector: 'my-app',
template: `
<div>
<div *ngFor="let item of toDos;let index = index;">
<input [(ngModel)]="item" placeholder="item">
</div>
Below Should be binded to above input box
<div *ngFor="let item of toDos">
<label>item</label>
</div>
</div>
`,
directives: [MdButton, MdInput]
)
export class AppComponent
toDos: string[] =["Todo1","Todo2","Todo3"];
constructor()
ngOnInit()
【问题讨论】:
你得到一个错误,因为你不能这样做:``` `` 你不能绑定 ng-模型到参考变量“项目”。我不确定您要完成什么。你能详细说明一下吗? 没关系,我找到了需要包含 trackByIndex 然后绑定到 toDos [index] 的解决方案。很快就会更新 plunkr。 发布一个答案 :-) 【参考方案1】:在挖掘之后,我需要在 ngFor 上使用 trackBy。更新了 plnkr 和下面的代码。希望这对其他人有帮助。
Working Plnkr
@Component(
selector: 'my-app',
template: `
<div>
<div *ngFor="let item of toDos;let index = index;trackBy:trackByIndex;">
<input [(ngModel)]="toDos[index]" placeholder="item">
</div>
Below Should be binded to above input box
<div *ngFor="let item of toDos">
<label>item</label>
</div>
</div>
`,
directives: [MdButton, MdInput]
)
export class AppComponent
toDos: string[] =["Todo1","Todo2","Todo3"];
constructor()
ngOnInit()
trackByIndex(index: number, obj: any): any
return index;
【讨论】:
实际上trackBy
在您的代码中并不重要!重要的是[(ngModel)]="toDos[index]"
而不是[(ngModel)]="item"
@Lars 没有 trackBy 输入失去焦点,似乎挂在我的经验中。
没有 trackBy ngFor
每次更改数组中的字符串时都会重新创建 DOM,因此这是完全必要的。
@Lars trackBy:trackByIndex;
是必需的,否则你会在第一次按键后失去对输入的关注。
如果你的 <input>
在 <form>
中,角度强制你在输入中输入一个名称,在这种情况下,当修改字符串数组时,它会显示 3 次 "Todo3"
但是不会抛出任何错误,其他一切都会正常工作。您可以将名称替换为 [ngModelOptions]="standalone: true"
,以便在输入中获得所有 3 个不同的字符串。【参考方案2】:
由于两个原因,您所做的事情不起作用。
您必须使用 toDos[index] 而不是带有 ngModel 的项目 (Read for more info) 每个输入都必须有一个唯一的名称这是解决您问题的有效解决方案。
<div>
<div *ngFor="let item of toDos;let index = index;">
<input name=aindex [(ngModel)]="toDos[index]" placeholder="item">
</div>
Below Should be binded to above input box
<div *ngFor="let item of toDos">
<label>item</label>
</div>
【讨论】:
我搜索了多个问题,直到我得到了这个问题的答案。我的问题是“每个输入都必须有一个唯一的名称”。这正是我所需要的! 很高兴我能帮上忙 我也一样 :)。为我节省了大量时间。谢谢老哥 “每个输入都必须有一个唯一的名称” - 这救了我。谢谢大佬 “每个输入都必须有一个唯一的名称”为我修复了它。我的输入值在提交后消失了,但现在它们留在那里,因为每个输入都有不同的名称。非常感谢!【参考方案3】:试试这个
@Component(
selector: 'my-app',
template: `
<div>
<div *ngFor="let item of toDos;let index = index;">
<input [(ngModel)]="item.text" placeholder="item.text">
</div>
Below Should be binded to above input box
<div *ngFor="let item of toDos">
<label>item.text</label>
</div>
</div>
`,
directives: [MdButton, MdInput]
)
export class AppComponent
toDos: any[] =[text:"Todo1",text:"Todo2",text:"Todo3"];
constructor()
ngOnInit()
【讨论】:
投反对票的原因如下: 1. 不需要向数组添加密钥。也可以使用字符串数组来完成。所以冗余。 2. "trackBy:trackByIndex;"在这种情况下是必要的,因为如果更改输入,它将更改“toDos”数组的值,这将反过来重新渲染完整的“ngFor”。使用“trackBy:trackByIndex;”不允许重新渲染,因为此代码 ngFor 仅在索引更改时才会重新渲染。 在数组中加一个key表示任何对象都可以在数组中并且可以被这个方法引用,这有助于更多更深入的理解;虽然这里没有使用索引,如下面的 Lasitha Yapa 所示【参考方案4】:您必须使用 name + index 向 ngModel 添加 name 属性以使其唯一。
<mat-form-field
#fileNameRef
appearance="fill"
color="primary"
floatLabel="auto"
>
<input
matInput
#fileNameCtrl="ngModel"
name="originalName index "
[(ngModel)]="file.originalName"
type="text"
autocomplete="off"
autocapitalize="off"
readonly
/>
</mat-form-field>
【讨论】:
@Tomerikoo 谢谢。我编辑了我的答案。以上是关于Angular 2 - NgFor 中与 NgModel 的 2 路绑定的主要内容,如果未能解决你的问题,请参考以下文章