5

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.

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

2
  • 1
    Before I try to answer the question, I would like to point out that there is a typo in the formGroupName directive in the code that you shared (forGroupName in your code). I just want to make sure that this isn't the source of the problem before writting a proper answer ? Commented Apr 29, 2024 at 15:42
  • thanks, it was not the typo that caused the problem Commented Apr 29, 2024 at 15:47

1 Answer 1

2

You need to define the formArrayName="sections" above the for loop, so that it's 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 it's clear that the block of code belongs 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

Sign up to request clarification or add additional context in comments.

1 Comment

perfect, thanks, I had just added the formArrayName="sections" but I missed the index being the formGroupName. It works now!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.