Trouble binding nested arrays of checkboxes in Angular 6 reactive form












0















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!










share|improve this question



























    0















    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!










    share|improve this question

























      0












      0








      0








      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!










      share|improve this question














      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






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Jan 1 at 6:48









      christokchristok

      3951318




      3951318
























          1 Answer
          1






          active

          oldest

          votes


















          0














          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>





          share|improve this answer























            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
            });


            }
            });














            draft saved

            draft discarded


















            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









            0














            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>





            share|improve this answer




























              0














              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>





              share|improve this answer


























                0












                0








                0







                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>





                share|improve this answer













                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>






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Jan 1 at 16:34









                christokchristok

                3951318




                3951318
































                    draft saved

                    draft discarded




















































                    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.




                    draft saved


                    draft discarded














                    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





















































                    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







                    Popular posts from this blog

                    Monofisismo

                    Angular Downloading a file using contenturl with Basic Authentication

                    Olmecas