I'm using ng-select on a form, but now I want to wrap a specific configuration of this on a custom component. The problem is I'm using a FormArray
which contains several of this, in the next way:
this.profileForm = this.formBuilder.group(
{
...
linkedRoles: this.formBuilder.array([])
}
);
This linkedRoles
is populated with the next FormGroup
:
let fgRoles: FormGroup;
for (let i = 0; i < this.userRoles.length; i++) {
fgRoles = this.formBuilder.group({
activeRole: [{ value: null }],
roles: [{ value: null }]
});
this.linkedRoles.push(fgRoles);
this.linkedRoles.controls[i].setValue({
activeRole: this.userRoles[i].role,
roles: this.extractUserRoles(this.userRoles[i])
});
A getter is created for simplicity too:
get linkedRoles(): FormArray {
return <FormArray>this.profileForm.get("linkedRoles");
}
After this, in my template, I was using this composition which was working perfectly:
<form [formGroup]="profileForm">
...
<table>
...
<tbody>
<tr formArrayName="linkedRoles"
*ngFor="let usuR of userRoles;
let idx = index"
>
...
<td data-label="Roles" [formGroupName]="idx">
<ng-select #rolesNgSelect
[hideSelected]="false"
bindLabel="rol"
...
formControlName="roles"
>
<ng-template ng-label-tmp let-item="item">
...
</ng-template>
<ng-template ng-option-tmp let-item="item">
...
</ng-template>
</ng-select>
</td>
</tr>
</tbody>
</table>
</form>
Now, I'm trying to substitute the ng-select
by my custom component role-selector
, which basically receives all the necessary properties from the ng-select
and wraps this in the template. The change in my previous template is as follows:
<tr formArrayName="linkedRoles"
*ngFor="let usuR of userRoles;
let idx = index;
let ctrlRol of linkedRoles.controls"
>
<td>
<app-role-selector
[hideSelected]="false"
bindLabel="rol"
...
formControlName="roles"
>
</app-role-selector>
</td>
</tr>
With this subtle change, I'm receiving the next error in console:
ERROR Error: No value accessor for form control with path: 'linkedRoles -> 0 -> roles'
Strangest thing is, when I click the unstyled box that appears, it loads and works almost fine. Should I move my formControlName
tag to the ng-select
inside my component's template?
POSSIBLE SOLUTION
Looking for a solution, I found the interesting ngDefaultControl
. Adding this directive to my custom component makes it behave as expected. Now it looks like this:
<app-role-selector
[hideSelected]="false"
bindLabel="rol"
...
ngDefaultControl
formControlName="roles"
>
The only counterside is I don't fully understand why this is necessary and if this is the best solution.