Dynamic nested reactive form: ExpressionChangedAfterItHasBeenCheckedError

Discussão em 'Angular' iniciado por Erik Nijland, Novembro 19, 2024.

  1. Erik Nijland

    Erik Nijland Guest

    My reactive form is three component levels deep. The parent component creates a new form without any fields and passes it down to child components.

    At first the outer form is valid. Later on a child component adds new form elements with validators (that fail) making the outer form invalid.

    I am getting an ExpressionChangedAfterItHasBeenCheckedError error in the console. I want to fix that error.

    Somehow this only happens when I add the third level of nesting. The same approach seemed to work for two levels of nesting.

    Plunker: https://plnkr.co/edit/GymI5CqSACFEvhhz55l1?p=preview

    Parent component

    @Component({
    selector: 'app-root',
    template: `
    myForm.valid: <b>{{myForm.valid}}</b>
    <form>
    <app-subform [myForm]="myForm"></app-subform>
    </form>
    `
    })
    export class AppComponent implements OnInit {
    ...

    ngOnInit() {
    this.myForm = this.formBuilder.group({});
    }
    }


    Sub component

    @Component({
    selector: 'app-subform',
    template: `
    <app-address-form *ngFor="let addressData of addressesData;"
    [addressesForm]="addressesForm">
    </app-address-form>
    `
    })
    export class SubformComponent implements OnInit {
    ...

    addressesData = [...];

    constructor() { }

    ngOnInit() {
    this.addressesForm = new FormArray([]);
    this.myForm.addControl('addresses', this.addressesForm);
    }


    Child component

    @Component({
    selector: 'app-address-form',
    template: `
    <input [formControl]="addressForm.controls.addressLine1">
    <input [formControl]="addressForm.controls.city">
    `
    })
    export class AddressFormComponent implements OnInit {
    ...

    ngOnInit() {
    this.addressForm = this.formBuilder.group({
    addressLine1: [
    this.addressData.addressLine1,
    [ Validators.required ]
    ],
    city: [
    this.addressData.city
    ]
    });

    this.addressesForm.push(this.addressForm);
    }
    }


    [​IMG]

    Continue reading...

Compartilhe esta Página