Skip to content

Instantly share code, notes, and snippets.

@jhades
Last active March 30, 2023 09:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jhades/a8a16ac802db0bdf0e38953fbbaa05dc to your computer and use it in GitHub Desktop.
Save jhades/a8a16ac802db0bdf0e38953fbbaa05dc to your computer and use it in GitHub Desktop.
Angular Form Array: Complete Guide - blog.angular-university.io/angular-form-array/
form = this.fb.group({
title: ['', {
validators: [
Validators.required,
Validators.minLength(5),
Validators.maxLength(60)
],
asyncValidators: [courseTitleValidator(this.courses)],
updateOn: 'blur'
}],
releasedAt: [new Date(), Validators.required],
category: ['BEGINNER', Validators.required],
downloadsAllowed: [false, Validators.requiredTrue],
longDescription: ['', [Validators.required, Validators.minLength(3)]]
});
@Component({
selector: 'form-array-example',
templateUrl: 'form-array-example.component.html',
styleUrls: ['form-array-example.component.scss']
})
export class FormArrayExampleComponent {
form = this.fb.group({
... other form controls ...
lessons: this.fb.array([])
});
constructor(private fb:FormBuilder) {}
get lessons() {
return this.form.controls["lessons"] as FormArray;
}
}
<button mat-mini-fab (click)="addLesson()">
<mat-icon class="add-course-btn">add</mat-icon>
</button>
addLesson() {
const lessonForm = this.fb.group({
title: ['', Validators.required],
level: ['beginner', Validators.required]
});
this.lessons.push(lessonForm);
}
deleteLesson(lessonIndex: number) {
this.lessons.removeAt(lessonIndex);
}
<h3>Add Course Lessons:</h3>
<div class="add-lessons-form" [formGroup]="form">
<ng-container formArrayName="lessons">
<ng-container *ngFor="let lessonForm of lessons.controls; let i = index">
<div class="lesson-form-row" [formGroup]="lessonForm">
<mat-form-field appearance="fill">
<input matInput
formControlName="title"
placeholder="Lesson title">
</mat-form-field>
<mat-form-field appearance="fill">
<mat-select formControlName="level"
placeholder="Lesson level">
<mat-option value="beginner">Beginner</mat-option>
<mat-option value="intermediate">Intermediate</mat-option>
<mat-option value="advanced">Advanced</mat-option>
</mat-select>
</mat-form-field>
<mat-icon class="delete-btn" (click)="deleteLesson(i)">
delete_forever</mat-icon>
</div>
</ng-container>
</ng-container>
<button mat-mini-fab (click)="addLesson()">
<mat-icon class="add-course-btn">add</mat-icon>
</button>
</div>
@Component({
selector: 'form-array-example',
templateUrl: 'form-array-example.component.html',
styleUrls: ['form-array-example.component.scss']
})
export class FormArrayExampleComponent {
form = this.fb.group({
... other form controls ...
lessons: this.fb.array([])
});
constructor(private fb:FormBuilder) {}
get lessons() {
return this.form.controls["lessons"] as FormArray;
}
addLesson() {
const lessonForm = this.fb.group({
title: ['', Validators.required],
level: ['beginner', Validators.required]
});
this.lessons.push(lessonForm);
}
deleteLesson(lessonIndex: number) {
this.lessons.removeAt(lessonIndex);
}
}
@estebandlp
Copy link

estebandlp commented Jun 20, 2021

Hi! I'm not sure if this comment it's okay or I would have to write it in another place, so first of all I'm sorry if I'm wrong.

I did exactly what you said, and I have the next error:

ERROR in [...]component.html:89:38 - error TS2740: Type 'AbstractControl' is missing the following properties from type 'FormGroup': controls, registerControl, addControl, removeControl, and 3 more.
89                 <div class="package" [formGroup]="mlFullPackage">

mlFullPackage is the variable defined in the ngFor.

So my question is: do you know why I have this error?

The component has the next structure:

  editForm = this.fb.group({
    id: [],
    personalId: [],
    trackingNumber: [null, [Validators.required]],
    sendDate: [moment().format(DATE_FORMAT), [Validators.required]],
    arrivalDate: [moment().format(DATE_FORMAT), [Validators.required]],
    creationDate: [],
    observations: [],
    mlFullPackages: this.fb.array([]),
  });
get mlFullPackages(): FormArray {
   return this.editForm.controls['mlFullPackages'] as FormArray;
 }
addMLPackage(): void {
   const mlPackage = this.fb.group({
     trackingNumber: [null, Validators.required],
   });

   this.mlFullPackages.push(mlPackage);
 }
  deleteMLPackage(mlPackageIndex: number) : void{
    this.mlFullPackages.removeAt(mlPackageIndex);
  }`

Thank you so much!

@UmbertoBagnati
Copy link

I have the same Error of @estebandlp.

@pbrianmackey
Copy link

Change:
<div class="lesson-form-row" [formGroup]="lessonForm">
to
<div class="lesson-form-row" [formGroupName]="i">

@olaneat
Copy link

olaneat commented Jun 15, 2022

i have an error while trying the lessons.push(), which of the lessons are u referring to, the function or the form element, i gave my function a different name from the form element so im getting a not defined error

@BrunoPicolo
Copy link

BrunoPicolo commented Sep 21, 2022

For me the error disappears by casting the lessonsForm to FormGroup. To do this I created a method to do the casting and used it in the template.

In the template: <div class="lesson-form-row" [formGroup]="toFormGroup(lessonForm)">

In the class: toFormGroup = (form: AbstractControl) => form as FormGroup;

@gmurimi
Copy link

gmurimi commented Feb 17, 2023

I am wondering the same

@rofrol
Copy link

rofrol commented Mar 30, 2023

The error Type 'AbstractControl<any, any>' is missing the following properties from type 'FormGroup<any>' happens when you have in tsconfig.json:

  "angularCompilerOptions": {
    "strictTemplates": true
  },

Solution with pipe (I couldn't manage to make it work with generic pipe like in https://stackoverflow.com/a/69466380/588759):

import { Pipe, PipeTransform } from '@angular/core';
import { AbstractControl, FormGroup } from '@angular/forms';

/**
 * https://stackoverflow.com/a/72517767/588759
 * https://stackoverflow.com/a/67059770/588759
 */

@Pipe({
  name: 'formGroup',
})
export class FormGroupPipe implements PipeTransform {
  transform(value: AbstractControl): FormGroup<(typeof value)['value']> {
    return value as FormGroup<(typeof value)['value']>;
  }
}

and use as [formGroup]="lessonForm | formGroup"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment