Based on these 2 urls:
- https://brophy.org/post/nested-reactive-forms-in-angular2/ (1)
- https://stackblitz.com/edit/monolithic-reactive-form-async-fill (2)
I would like:
- a MasterComponent
- with a ListComponent
- and a ListItemComponent
MasterComponent.ts
public data: Data;
public form: FormGroup = this.fb.group({});
formInitialized(name: string, form: FormGroup) {
this.form.addControl(name, form);
}
MasterComponent.html
<app-list [parentForm]="form"
[items]="data.items"
(formReady)="formInitialized('items', $event)"></app-list>
ListComponent.ts
@Input() parentForm: FormGroup;
@Input() items: item[];
@Output() formReady = new EventEmitter<AbstractControl>()
public itemsForm: FormArray;
formInitialized(itemForm: FormGroup) {
debugger;
this.itemsForm.push(itemForm);
}
ngOnInit() {
debugger;
this.itemsForm = new FormArray([]);
this.formReady.emit(this.itemsForm);
}
ListComponent.html
<div [formGroup]="parentForm">
<div formArrayName="items">
<ng-template let-item let-last="last" let-i="index" ngFor [ngForOf]="items">
<app-item [itemsForm]="parentForm.controls.items"
[item]="item"
(formReady)="formInitialized($event)">
</app-item>
</ng-template>
</div>
</div>
item.component.ts
@Input() itemsForm: FormArray;
@Input() item: Item;
@Output() formReady = new EventEmitter<AbstractControl>()
public itemForm: FormGroup;
ngOnInit() {
this.itemForm = this._formBuilder.group({title: [item.title || '', Validators.required],});
this.formReady.emit(this.itemForm);
}
item.component.html
<div class="md-padding" [formGroup]="itemForm">
<mat-form-field flex>
<input #title
name="title"
matInput
type="text"
placeholder="Title"
formControlName="title"
maxlength="150"
required />
<mat-error *ngIf="title.pristine || !title.errors">
<div *ngIf="title.errors?.required">
this field is required.
</div>
<div *ngIf="title.errors?.maxlength">
max length is 150.
</div>
</mat-error>
<mat-hint align="end">{{title.value.length}} / 150</mat-hint>
</mat-form-field>
</div>
I have an error with code:
MasterComponent.html:12 ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'Items: [object Object],[object Object]core.js:8445)
at expressionChangedAfterItHasBeenCheckedError (core.js:8433)
at checkBindingNoChanges (core.js:8535)
at checkNoChangesNodeInline (core.js:11403)
at checkNoChangesNode (core.js:11390)
at debugCheckNoChangesNode (core.js:11997)
at debugCheckDirectivesFn (core.js:11925)
at Object.eval [as updateDirectives] (MasterComponent.html:12)
at Object.debugUpdateDirectives [as updateDirectives] (core.js:11914)
at checkNoChangesView (core.js:11289)
I like the concept where the child component is in charge to give the formGroup to the master component 1. The problem with the solution 1 is the child component can't update the mastercomponent (see the issue https://github.com/brophdawg11/ng-playground/issues/5). So I adapted the solution 1 with the solution 2.
But it doesnt work. Is there a way to fix the problem? Or do you have a good tutorial to propose?
Thanks
(formReady)="formInitialized($event)". Looks like your using an@Output()binding to pass internal references to other components, and then the inner state of that component is changed by outsiders. Which explains why you're getting the change error.