Angular 表单 - 如何为 formArrayName 中的 select 绑定 formControlName 以使用对象
Angular forms - How to bind formControlName for select in formArrayName to use objects
我正在尝试弄清楚如何在 formArrayName 中为 select
设置绑定对象复杂绑定。我猜 formControlName 应该引用数组中的当前项,但我不知道如何访问它。
<div formArrayName="users">
<div *ngFor="let u of users.controls; let i=index" [formGroupName]='i'>
user {{i}}: <select formControlName='id'[compareWith]="compareFn">
<option *ngFor="let a of avaliableUsers" [ngValue]='a'>{{a.login}}</option>
</select>
</div>
</div>
我已经用单个 select(按我想要的方式工作)和将值推入 "id" 的数组创建了演示。
https://stackblitz.com/edit/angular-d2uaa1
非常感谢任何帮助。
编辑
要点:
- 将整个
UsersGroup
对象与所有属性(id 和登录名)绑定
- 最少附加代码 (KISS)
解决方案(基于@JT_82评论)
<div *ngFor="let u of users.controls; let i=index">
<select [formControlName]='i' [compareWith]="compareFn">
<option *ngFor="let a of avaliableUsers" [ngValue]='a'>{{a.login}}</option>
</select>
</div>
ngOnInit(): void {
this.owner.patchValue(this.group.owner);
this.group.users.forEach(u => {
this.users.push(this.fb.control(u))
});
}
compareFn(a, b): boolean {
return a.id === b.id;
}
编辑: 根据 OP 的意愿,我们希望将对象保留为 select 中的值,因为我们可以而不是在 formarray 中使用表单组,只需按下 formcontrols,然后包含对象值:
this.group.users.forEach(u => {
this.users.push(this.fb.control(u)) // just push formcontrol!
});
然后在模板中标记:
<select [formControlName]='i' [compareWith]="compareFn">
<option *ngFor="let a of avaliableUsers" [ngValue]='a'>{{a.login}}</option>
</select>
由于我们现在使用对象值作为表单控件,因此在尝试匹配预设值时,我们需要一个 compareWith 函数:
compareFn(a, b): boolean {
return a.id === b.id;
}
原始答案:
我可能会在 select 更改时调用一个函数,然后从 availableUsers
中找到用户,并使用找到的用户设置 login
的表单值。所以模板:
<select formControlName='id' (change)="findLogin(u)">
<option *ngFor="let a of avaliableUsers" [ngValue]='a.id'>{{a.login}}</option>
</select>
因此您可以删除 compareWith
,因为我们现在使用数字作为值。然后是 findLogin
函数,我们从迭代中传递当前的表单组:
findLogin(group: FormGroup) {
const user = this.avaliableUsers.find(x => x.id === group.get('id').value)
group.get('login').setValue(user.login);
}
你的分叉 StackBlitz
我正在尝试弄清楚如何在 formArrayName 中为 select
设置绑定对象复杂绑定。我猜 formControlName 应该引用数组中的当前项,但我不知道如何访问它。
<div formArrayName="users">
<div *ngFor="let u of users.controls; let i=index" [formGroupName]='i'>
user {{i}}: <select formControlName='id'[compareWith]="compareFn">
<option *ngFor="let a of avaliableUsers" [ngValue]='a'>{{a.login}}</option>
</select>
</div>
</div>
我已经用单个 select(按我想要的方式工作)和将值推入 "id" 的数组创建了演示。 https://stackblitz.com/edit/angular-d2uaa1
非常感谢任何帮助。
编辑
要点:
- 将整个
UsersGroup
对象与所有属性(id 和登录名)绑定 - 最少附加代码 (KISS)
解决方案(基于@JT_82评论)
<div *ngFor="let u of users.controls; let i=index">
<select [formControlName]='i' [compareWith]="compareFn">
<option *ngFor="let a of avaliableUsers" [ngValue]='a'>{{a.login}}</option>
</select>
</div>
ngOnInit(): void {
this.owner.patchValue(this.group.owner);
this.group.users.forEach(u => {
this.users.push(this.fb.control(u))
});
}
compareFn(a, b): boolean {
return a.id === b.id;
}
编辑: 根据 OP 的意愿,我们希望将对象保留为 select 中的值,因为我们可以而不是在 formarray 中使用表单组,只需按下 formcontrols,然后包含对象值:
this.group.users.forEach(u => {
this.users.push(this.fb.control(u)) // just push formcontrol!
});
然后在模板中标记:
<select [formControlName]='i' [compareWith]="compareFn">
<option *ngFor="let a of avaliableUsers" [ngValue]='a'>{{a.login}}</option>
</select>
由于我们现在使用对象值作为表单控件,因此在尝试匹配预设值时,我们需要一个 compareWith 函数:
compareFn(a, b): boolean {
return a.id === b.id;
}
原始答案:
我可能会在 select 更改时调用一个函数,然后从 availableUsers
中找到用户,并使用找到的用户设置 login
的表单值。所以模板:
<select formControlName='id' (change)="findLogin(u)">
<option *ngFor="let a of avaliableUsers" [ngValue]='a.id'>{{a.login}}</option>
</select>
因此您可以删除 compareWith
,因为我们现在使用数字作为值。然后是 findLogin
函数,我们从迭代中传递当前的表单组:
findLogin(group: FormGroup) {
const user = this.avaliableUsers.find(x => x.id === group.get('id').value)
group.get('login').setValue(user.login);
}
你的分叉 StackBlitz