typescript - Angular FormGroup inuti FormArray med ny kontrollflöde
Jag har ett reaktivt Angular-formulär som har ett formArray av formGroups kallade 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])
});
Jag använder reaktiva formulär här och jag vill bygga HTML-formuläret för att matcha denna uppsättning. Jag har följande avsnitt av mitt formulär som försöker använda det nya kontrollflödet för att rendera sections formulärgruppen inuti formulärmatrisen:
<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>
PROBLEMET:
De indata som listas ovan och som delar namn med den överordnade formulärgruppen är bundna till kontrollerna i den överordnade formulärgruppen och inte kontrollerna inne i formmatrisen. Så vad jag än skriver i sectionTitle-indatan uppdaterar egenskapen title i den överordnade gruppen.
Jag trodde att genom att sätta formGroupName i div:en till section <div forGroupName="section"> skulle ändra kontexten för kontrollerna inuti den. Det gör det inte.
Kan någon hjälpa mig att lista ut hur man binder kontrollerna inuti formulärarrayen med tanke på att det kommer att finnas flera "sektion"-formulärgrupper inuti den arrayen som behöver rendera sina respektive kontroller
Svar #1
Du behöver definiera formArrayName="sections" ovanför for-loopen, så att det är tydligt att kontrollerna tillhör form-arrayen.
Sedan på det första elementet inuti for-loopen behöver vi sätta [formGroupName]="index" så att det är klart att kodblocket tillhör det n:te elementet i formulärarrayens formGroup:
...
<div cy-data="session-sections" formArrayName="sections">
@for (section of sessionForm.controls.sections.controls;let index = $index; track index) {
<div [formGroupName]="index">
...
Fullständig kod:
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-demonstration
