I'm trying to divide a Material Angular mat-step (from a mat-horizontal-stepper) into separate nested sub-forms components, and get a ExpressionChangedAfterItHasBeenCheckedError regarding the validity of the form.
This stackblitz demonstrates the problem: https://stackblitz.com/edit/mat-stepper-components
The nested components are in step one.
Interestingly enough, the problem doesn't happen if there is just one level of nesting (if steps do not have nested sub-forms), as demonstrated in step two.
Here are the main parts of the code:
create-profile.component.html
<mat-horizontal-stepper [linear]=true #stepper>
<mat-step [stepControl]="frmStepOne">
<ng-template matStepLabel>Step One Details</ng-template>
<form [formGroup]="frmStepOne"><ng-template matStepLabel>Step One</ng-template>
<step-one-component></step-one-component>
</form>
</mat-step>
<mat-step [stepControl]="frmStepTwo">
<ng-template matStepLabel>Step Two Details</ng-template>
<form [formGroup]="frmStepTwo">
<step-two-component></step-two-component>
</form>
</mat-step>
</mat-horizontal-stepper>
create-profile.component.ts
//...
constructor(private fb: FormBuilder) {
this.frmStepOne = new FormGroup({});
this.frmStepTwo = new FormGroup({});
}
step-one.component.html
<step-one-child-one></step-one-child-one>
step-one.component.ts
// nothing interesting, just component boilerplate
step-one-child-one.component.html
<mat-form-field>
<input matInput formControlName="name" placeholder="Name" required>
</mat-form-field>
step-one-child-one.component.ts
@Component({
selector: 'step-one-child-one',
templateUrl: './step-one-child-one.component.html',
viewProviders: [
{
provide: ControlContainer,
useExisting: FormGroupDirective
}
]
})
export class StepOneChildOneComponent {
constructor(private parent: FormGroupDirective) {
}
ngOnInit() {
this.parent.form.addControl('name', new FormControl('', [Validators.required]));
}
}