Trouble binding nested arrays of checkboxes in Angular 6 reactive form
I have a dynamic reactive form with the following structure, which is intended to create a matrix consisting of an arbitrary number of users each with an arbitrary number of userRoles:
this.form = this.formBuilder.group({
users: this.formBuilder.array(
this.usersRoles.map(
urs => this.formBuilder.group({
userRoles: new FormArray(
urs.map(r => new FormControl(r))
)
})
)
)
});
In the above code, this.usersRoles is an an array of boolean values (e.g 0: true, 1: false, 2: false, etc) representing the initial state of a checkbox stored as FormControl(r).
When this structure is populated with data, the form is rendered in a table as follows:
<tr formArrayName="users" *ngFor="let user of form['controls']['users']['controls']; index as u">
<td *ngFor="let userRole of user['controls']['userRoles']['controls']; index as i">
<input type="checkbox" [formControlName]="i">
</td>
</tr>
My problem is with binding the rendered form to the underlying array of controls. As written above, this html generates the error "control.registerOnChange is not a function", which seems to indicate that the template cannot find the control from the form group.
I feel like I am missing something simple here, but can't quite figure out what it might be. For instance, I tried adding formArrayName="userRoles" to the td that wraps the checkbox, thinking that would be required in order to differentiate the checkboxes in one user row from another, but then received "Cannot find control with path: 'users -> userRoles'".
Interestingly, the first user order renders fine (albeit without any boxes being checked) before triggering errors so I think I'm on to something with that forArrayName thing... Any help is much appreciated!
angular6 angular-reactive-forms
add a comment |
I have a dynamic reactive form with the following structure, which is intended to create a matrix consisting of an arbitrary number of users each with an arbitrary number of userRoles:
this.form = this.formBuilder.group({
users: this.formBuilder.array(
this.usersRoles.map(
urs => this.formBuilder.group({
userRoles: new FormArray(
urs.map(r => new FormControl(r))
)
})
)
)
});
In the above code, this.usersRoles is an an array of boolean values (e.g 0: true, 1: false, 2: false, etc) representing the initial state of a checkbox stored as FormControl(r).
When this structure is populated with data, the form is rendered in a table as follows:
<tr formArrayName="users" *ngFor="let user of form['controls']['users']['controls']; index as u">
<td *ngFor="let userRole of user['controls']['userRoles']['controls']; index as i">
<input type="checkbox" [formControlName]="i">
</td>
</tr>
My problem is with binding the rendered form to the underlying array of controls. As written above, this html generates the error "control.registerOnChange is not a function", which seems to indicate that the template cannot find the control from the form group.
I feel like I am missing something simple here, but can't quite figure out what it might be. For instance, I tried adding formArrayName="userRoles" to the td that wraps the checkbox, thinking that would be required in order to differentiate the checkboxes in one user row from another, but then received "Cannot find control with path: 'users -> userRoles'".
Interestingly, the first user order renders fine (albeit without any boxes being checked) before triggering errors so I think I'm on to something with that forArrayName thing... Any help is much appreciated!
angular6 angular-reactive-forms
add a comment |
I have a dynamic reactive form with the following structure, which is intended to create a matrix consisting of an arbitrary number of users each with an arbitrary number of userRoles:
this.form = this.formBuilder.group({
users: this.formBuilder.array(
this.usersRoles.map(
urs => this.formBuilder.group({
userRoles: new FormArray(
urs.map(r => new FormControl(r))
)
})
)
)
});
In the above code, this.usersRoles is an an array of boolean values (e.g 0: true, 1: false, 2: false, etc) representing the initial state of a checkbox stored as FormControl(r).
When this structure is populated with data, the form is rendered in a table as follows:
<tr formArrayName="users" *ngFor="let user of form['controls']['users']['controls']; index as u">
<td *ngFor="let userRole of user['controls']['userRoles']['controls']; index as i">
<input type="checkbox" [formControlName]="i">
</td>
</tr>
My problem is with binding the rendered form to the underlying array of controls. As written above, this html generates the error "control.registerOnChange is not a function", which seems to indicate that the template cannot find the control from the form group.
I feel like I am missing something simple here, but can't quite figure out what it might be. For instance, I tried adding formArrayName="userRoles" to the td that wraps the checkbox, thinking that would be required in order to differentiate the checkboxes in one user row from another, but then received "Cannot find control with path: 'users -> userRoles'".
Interestingly, the first user order renders fine (albeit without any boxes being checked) before triggering errors so I think I'm on to something with that forArrayName thing... Any help is much appreciated!
angular6 angular-reactive-forms
I have a dynamic reactive form with the following structure, which is intended to create a matrix consisting of an arbitrary number of users each with an arbitrary number of userRoles:
this.form = this.formBuilder.group({
users: this.formBuilder.array(
this.usersRoles.map(
urs => this.formBuilder.group({
userRoles: new FormArray(
urs.map(r => new FormControl(r))
)
})
)
)
});
In the above code, this.usersRoles is an an array of boolean values (e.g 0: true, 1: false, 2: false, etc) representing the initial state of a checkbox stored as FormControl(r).
When this structure is populated with data, the form is rendered in a table as follows:
<tr formArrayName="users" *ngFor="let user of form['controls']['users']['controls']; index as u">
<td *ngFor="let userRole of user['controls']['userRoles']['controls']; index as i">
<input type="checkbox" [formControlName]="i">
</td>
</tr>
My problem is with binding the rendered form to the underlying array of controls. As written above, this html generates the error "control.registerOnChange is not a function", which seems to indicate that the template cannot find the control from the form group.
I feel like I am missing something simple here, but can't quite figure out what it might be. For instance, I tried adding formArrayName="userRoles" to the td that wraps the checkbox, thinking that would be required in order to differentiate the checkboxes in one user row from another, but then received "Cannot find control with path: 'users -> userRoles'".
Interestingly, the first user order renders fine (albeit without any boxes being checked) before triggering errors so I think I'm on to something with that forArrayName thing... Any help is much appreciated!
angular6 angular-reactive-forms
angular6 angular-reactive-forms
asked Jan 1 at 6:48
christokchristok
3951318
3951318
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
Indeed this turned out to be an issue of needing to add some more attributes to the markup, complicated by the use of tables, which limit the opportunity to nest, as one might do with divs. Fortunately we have ng-container to help with that.
The key here was to ensure that the html elements reflected the form definition, so we needed a repeating element (ng-container) for the parent array - marked with formArrayName="users", and another repeating element (td) marked with formArrayName="userRoles" for the child array. The child array needed a wrapper as well marked with formGroupName which our tr provided. This gets a dynamic name from the index of the parent array ngFor.
The template frag below works perfectly.
<ng-container formArrayName="users" *ngFor="let user of form['controls']['users']['controls']; index as u">
<tr [formGroupName]="u">
<td formArrayName="userRoles" *ngFor="let userRole of user['controls']['userRoles']['controls']; index as i">
<input type="checkbox" [formControlName]="i">{{i}}
</td>
</tr>
</ng-container>
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53993553%2ftrouble-binding-nested-arrays-of-checkboxes-in-angular-6-reactive-form%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Indeed this turned out to be an issue of needing to add some more attributes to the markup, complicated by the use of tables, which limit the opportunity to nest, as one might do with divs. Fortunately we have ng-container to help with that.
The key here was to ensure that the html elements reflected the form definition, so we needed a repeating element (ng-container) for the parent array - marked with formArrayName="users", and another repeating element (td) marked with formArrayName="userRoles" for the child array. The child array needed a wrapper as well marked with formGroupName which our tr provided. This gets a dynamic name from the index of the parent array ngFor.
The template frag below works perfectly.
<ng-container formArrayName="users" *ngFor="let user of form['controls']['users']['controls']; index as u">
<tr [formGroupName]="u">
<td formArrayName="userRoles" *ngFor="let userRole of user['controls']['userRoles']['controls']; index as i">
<input type="checkbox" [formControlName]="i">{{i}}
</td>
</tr>
</ng-container>
add a comment |
Indeed this turned out to be an issue of needing to add some more attributes to the markup, complicated by the use of tables, which limit the opportunity to nest, as one might do with divs. Fortunately we have ng-container to help with that.
The key here was to ensure that the html elements reflected the form definition, so we needed a repeating element (ng-container) for the parent array - marked with formArrayName="users", and another repeating element (td) marked with formArrayName="userRoles" for the child array. The child array needed a wrapper as well marked with formGroupName which our tr provided. This gets a dynamic name from the index of the parent array ngFor.
The template frag below works perfectly.
<ng-container formArrayName="users" *ngFor="let user of form['controls']['users']['controls']; index as u">
<tr [formGroupName]="u">
<td formArrayName="userRoles" *ngFor="let userRole of user['controls']['userRoles']['controls']; index as i">
<input type="checkbox" [formControlName]="i">{{i}}
</td>
</tr>
</ng-container>
add a comment |
Indeed this turned out to be an issue of needing to add some more attributes to the markup, complicated by the use of tables, which limit the opportunity to nest, as one might do with divs. Fortunately we have ng-container to help with that.
The key here was to ensure that the html elements reflected the form definition, so we needed a repeating element (ng-container) for the parent array - marked with formArrayName="users", and another repeating element (td) marked with formArrayName="userRoles" for the child array. The child array needed a wrapper as well marked with formGroupName which our tr provided. This gets a dynamic name from the index of the parent array ngFor.
The template frag below works perfectly.
<ng-container formArrayName="users" *ngFor="let user of form['controls']['users']['controls']; index as u">
<tr [formGroupName]="u">
<td formArrayName="userRoles" *ngFor="let userRole of user['controls']['userRoles']['controls']; index as i">
<input type="checkbox" [formControlName]="i">{{i}}
</td>
</tr>
</ng-container>
Indeed this turned out to be an issue of needing to add some more attributes to the markup, complicated by the use of tables, which limit the opportunity to nest, as one might do with divs. Fortunately we have ng-container to help with that.
The key here was to ensure that the html elements reflected the form definition, so we needed a repeating element (ng-container) for the parent array - marked with formArrayName="users", and another repeating element (td) marked with formArrayName="userRoles" for the child array. The child array needed a wrapper as well marked with formGroupName which our tr provided. This gets a dynamic name from the index of the parent array ngFor.
The template frag below works perfectly.
<ng-container formArrayName="users" *ngFor="let user of form['controls']['users']['controls']; index as u">
<tr [formGroupName]="u">
<td formArrayName="userRoles" *ngFor="let userRole of user['controls']['userRoles']['controls']; index as i">
<input type="checkbox" [formControlName]="i">{{i}}
</td>
</tr>
</ng-container>
answered Jan 1 at 16:34
christokchristok
3951318
3951318
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53993553%2ftrouble-binding-nested-arrays-of-checkboxes-in-angular-6-reactive-form%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown