Reputation: 43
I'm trying to figure out how to set up a binding object complex binding for select
inside formArrayName. I'm guessing that formControlName should have reference to the current item in the array, but I don't know how to access it.
<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>
I've created demo with single select (which is working as I want) and array which is pushing value into "id". https://stackblitz.com/edit/angular-d2uaa1
Any help is greatly appreciated.
EDIT
Key points:
UsersGroup
objects with all properties (id and login)Solution (Based on @JT_82 comment)
<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;
}
Upvotes: 3
Views: 2728
Reputation: 73357
EDIT: Per OP's wishes, we would like to keep the object as value in the select, for that we can instead of using a formgroup inside the formarray, just push formcontrols, which then contains object values:
this.group.users.forEach(u => {
this.users.push(this.fb.control(u)) // just push formcontrol!
});
and then mark in template:
<select [formControlName]='i' [compareWith]="compareFn">
<option *ngFor="let a of avaliableUsers" [ngValue]='a'>{{a.login}}</option>
</select>
Since we are now using an object value as the formcontrol, when trying to match preset values, we need a compareWith function:
compareFn(a, b): boolean {
return a.id === b.id;
}
ORIGINAL ANSWER:
I would perhaps call a function when the select changes, and then find the user from availableUsers
and set the form value for login
with the found user. So template:
<select formControlName='id' (change)="findLogin(u)">
<option *ngFor="let a of avaliableUsers" [ngValue]='a.id'>{{a.login}}</option>
</select>
So you can remove compareWith
, since we are now using a number for the value. Then the findLogin
function where we pass the current formgroup from the iteration:
findLogin(group: FormGroup) {
const user = this.avaliableUsers.find(x => x.id === group.get('id').value)
group.get('login').setValue(user.login);
}
Your forked StackBlitz
Upvotes: 3