Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Angular FormGroup inside FormArray using new control flow

I have a reactive angular form that has a formArray of formGroups called sections:

  sectionForm = new FormGroup({
    title: new FormControl<string>('New Section', {nonNullable: true, validators: [Validators.required]}),
    subTitle: new FormControl<string>('section sub title', {nonNullable: true}),
    description: new FormControl<string>('description', {nonNullable: true}),
  });

  sessionForm = new FormGroup({
    title: new FormControl<string>('', {nonNullable: true, validators: [Validators.required]}),
    subTitle: new FormControl<string>('', {nonNullable: true, validators: [Validators.required]}),
    description: new FormControl<string>('', {nonNullable: true, validators: [Validators.required]}),
    sections: new FormArray([this.sectionForm])
  });

I am using reactive forms here and I want to build the html form to match this set up. I have the following section of my form that attempts to use the new control flow to render the sections form group inside the form array:

    <form [formGroup]="sessionForm" class="k-form k-form-md">
    <fieldset class="k-form-fieldset">

     <!--  other form controls ........ -->
      <div cy-data="session-sections">
        @for (section of sessionForm.controls.sections.controls; track $index) {
          <div forGroupName="section">
            <kendo-formfield cy-data="section-title">
              <kendo-label [for]="sectiontitle" text="Section Title"></kendo-label>
              <kendo-textbox
                #sectiontitle
                class="text-input"
                formControlName="title"
                [clearButton]="true"
                required
              ></kendo-textbox>
              <kendo-formerror>Error:Section Title Required</kendo-formerror>
            </kendo-formfield>
            <kendo-formfield cy-data="section-subtitle">
              <kendo-label [for]="sectionsubtitle" text="Section Sub Title"></kendo-label>
              <kendo-textbox
                #sectionsubtitle
                class="text-input"
                formControlName="subTitle"
                [clearButton]="true"
                required
              ></kendo-textbox>
              <kendo-formerror>Error:Section Sub Title Required</kendo-formerror>
            </kendo-formfield>
            <kendo-formfield cy-data="section-description">
              <kendo-label [for]="sectiondescription" text="Section Description"></kendo-label>
              <kendo-textarea
                #sectiondescription
                class="text-input"
                formControlName="description"
                required
              ></kendo-textarea>
              <kendo-formerror>Error:Section Description Required</kendo-formerror>
            </kendo-formfield>
          </div>
        }
      </div>

    </fieldset>
    </form>

THE PROBLEM:

the inputs listed above that share a name with the parent form group are bound to the controls in the parent form group and not the controls inside the form array. So whatever I enter in the sectionTitle input updates the parent title property.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

I thought that setting the formGroupName in the div to section <div forGroupName="section"> would change the context for the controls inside of it. It does not.

Can someone help me figure out how to bind the controls inside the form array considering that there will be multiple "section" form groups inside that array that need to render its respective controls

>Solution :

You need to define the formArrayName="sections" above the for loop, so that its clear the controls belong to the form array.

Then on the first element inside the for loop, we need to set the [formGroupName]="index" so that its clear that the block of code, belong to the nth element of the form array’s formGroup!

...
<div cy-data="session-sections" formArrayName="sections">
        @for (section of sessionForm.controls.sections.controls;let index = $index; track index) {
          <div [formGroupName]="index">
          ...

FULL CODE:

import { Component, ViewChild, ViewEncapsulation } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';
import { TextBoxComponent } from '@progress/kendo-angular-inputs';
import { FormArray, ReactiveFormsModule, Validators } from '@angular/forms';

@Component({
  selector: 'my-app',
  template: `
  <pre>{{sessionForm.value | json}}</pre>
        <form [formGroup]="sessionForm" class="k-form k-form-md">
    <fieldset class="k-form-fieldset">

     <!--  other form controls ........ -->
      <div cy-data="session-sections" formArrayName="sections">
        @for (section of sessionForm.controls.sections.controls;let index = $index; track index) {
          <div [formGroupName]="index">
            <kendo-formfield cy-data="section-title">
              <kendo-label [for]="sectiontitle" text="Section Title"></kendo-label>
              <kendo-textbox
                #sectiontitle
                class="text-input"
                formControlName="title"
                [clearButton]="true"
                required
              ></kendo-textbox>
              <kendo-formerror>Error:Section Title Required</kendo-formerror>
            </kendo-formfield>
            <kendo-formfield cy-data="section-subtitle">
              <kendo-label [for]="sectionsubtitle" text="Section Sub Title"></kendo-label>
              <kendo-textbox
                #sectionsubtitle
                class="text-input"
                formControlName="subTitle"
                [clearButton]="true"
                required
              ></kendo-textbox>
              <kendo-formerror>Error:Section Sub Title Required</kendo-formerror>
            </kendo-formfield>
            <kendo-formfield cy-data="section-description">
              <kendo-label [for]="sectiondescription" text="Section Description"></kendo-label>
              <kendo-textarea
                #sectiondescription
                class="text-input"
                formControlName="description"
                required
              ></kendo-textarea>
              <kendo-formerror>Error:Section Description Required</kendo-formerror>
            </kendo-formfield>
          </div>
        }
      </div>

    </fieldset>
    </form>
    `,
  encapsulation: ViewEncapsulation.None,
  styleUrls: ['./styles.css'],
})
export class AppComponent {
  sectionForm = new FormGroup({
    title: new FormControl<string>('New Section', {
      nonNullable: true,
      validators: [Validators.required],
    }),
    subTitle: new FormControl<string>('section sub title', {
      nonNullable: true,
    }),
    description: new FormControl<string>('description', { nonNullable: true }),
  });

  sessionForm = new FormGroup({
    title: new FormControl<string>('', {
      nonNullable: true,
      validators: [Validators.required],
    }),
    subTitle: new FormControl<string>('', {
      nonNullable: true,
      validators: [Validators.required],
    }),
    description: new FormControl<string>('', {
      nonNullable: true,
      validators: [Validators.required],
    }),
    sections: new FormArray([this.sectionForm]),
  });
}

Stackblitz Demo

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading