I'm trying to create a dynamic form array in Angular 17 with a child component handling part of the input. However, I'm encountering an error:
Type 'AbstractControl<any, any>' is missing the following properties from type 'FormGroup': controls, registerControl, addControl, removeControl, and 2 more.
Here's my code:
Parent component:
@Component({
selector: 'app',
template: `
<form [formGroup]="categoryForm" (ngSubmit)="onSubmit()">
<div formArrayName="categories" class="sections">
<div *ngFor="let category of categories.controls; let i=index">
<ng-container [formGroupName]="i">
<!-- CHILD COMPONENT -->
<app-category [formGroup]="category" [categories]="categories" [index]="i"></app-category>
<!-- ARRAY INPUTS -->
<!-- <div style="border: 1px solid blue; padding: 10px; width: 800px; margin: 5px; background: pink;">
<p><strong>Category : {{i+1}}</strong></p>
Category ID :
<input type="text" formControlName="categoryID" />
Category Name:
<input type="text" formControlName="categoryName" />
<button type="button" class="remove" (click)="removeCategory(i)">Remove Category</button>
</div> -->
</ng-container>
</div>
</div>
<button class="btn" type="button" (click)="addCategory()">Add Category</button>
<button class="btn" type="submit">Submit</button>
</form>
{{this.categoryForm.value | json}}
`,
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [ReactiveFormsModule, JsonPipe, NgFor, CategoryComponent],
})
export class AppComponent {
categoryForm!: FormGroup;
constructor(private fb: FormBuilder) {}
ngOnInit(): void {
this.categoryForm = this.fb.group({
categories: this.fb.array([]),
});
}
get categories(): FormArray {
return this.categoryForm.get('categories') as FormArray;
}
addCategory() {
this.categories.push(
this.fb.group({
categoryID: '',
categoryName: '',
sections: this.fb.array([]),
})
);
}
removeCategory(catIndex: number) {
this.categories.removeAt(catIndex);
}
onSubmit() {
console.log(this.categoryForm.value);
}
}
Child component:
@Component({
selector: 'app-category',
template: `
<form [formGroup]="formGroup">
<div style="border: 1px solid blue; padding: 10px; width: 800px; margin: 5px; background: pink;">
<p><strong>Category : {{index+1}}</strong></p>
Category ID :
<input type="text" formControlName="categoryID" />
Category Name:
<input type="text" formControlName="categoryName" />
<button type="button" class="remove" (click)="removeCategory()">Remove Category</button>
</div>
</form>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [ReactiveFormsModule, NgFor],
})
export class CategoryComponent {
@Input() categories!: FormArray;
@Input() formGroup!: FormGroup;
@Input() index!: number;
removeCategory() {
this.categories.removeAt(this.index);
}
}
I've created a form array in the parent component and tried to loop through it using *ngFor
, passing each form group to the child component. The child component receives the form group via @Input()
and handles part of the input fields.
Can someone help me understand why this error is occurring and how to resolve it? Thank you!
AbstractControl
to FormGroup
.[formGroupName]="i"
from <ng-container>
as it is not needed.<ng-container>
<!-- CHILD COMPONENT -->
<app-category [formGroup]="categoryFormGroup(i)" [categories]="categories" [index]="i"></app-category>
</ng-container>
categoryFormGroup(i: number) {
return this.categories.get(`${i}`) as FormGroup;
}