基于这2个网址:
我想:
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>
我的代码有错误:
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)
我喜欢子组件负责将formGroup提供给主组件1的概念。 解决方案1的问题是子组件无法更新master组件(请参阅问题https://github.com/brophdawg11/ng-playground/issues/5)。 因此,我使用解决方案1修改了解决方案2。
但它不起作用。有没有办法解决这个问题?或者你有一个很好的教程提议吗?
由于
答案 0 :(得分:3)
您可以只关注Brophy's example ...
创建formControl / formGroup时,不是让formReady发出, 而是只需通过@input传递父项将其添加到父项表单中。
诀窍是在正确的索引处更新表单,而不仅仅是推送到formArray ...
例如,
父母:(TS)
styleForm: FormGroup;
@Input() style: IStyle;
constructor(private fb: FormBuilder) {}
ngOnInit(): void {
this.styleForm = this.buildStyleForm();
}
buildStyleForm() {
return this.fb.group({
selected: false,
products: this.fb.array([])
});
}
父母:(HTML)
<ul class="style_product-list" formArrayName="products">
<li class="style_product" *ngFor="let product of style?.products; index as i">
<product [styleForm]="styleForm" [productIndex]="i" [product]="product"></product>
</li>
</ul>
孩子:
products: FormArray;
@Input() styleForm: FormGroup;
@Input() product: IProduct;
@Input() productIndex: number;
ngOnInit(): void {
this.productForm = this.buildProductFormGroup(this.product);
this.products = this.styleForm.controls.products as FormArray;
this.pushGroupIntoArray(this.products, this.productForm, this.productIndex);
}
pushGroupIntoArray(array: FormArray, group: FormGroup, index: number) {
if (array.at(index)) {
array.setControl(index, group);
} else {
array.push(group);
}
}
buildProductFormGroup(product: IProduct): FormGroup {
return <FormGroup > this.fb.group({
selected: [product && product.selected],
quantity: [product && product.quantity, Validators.required],
parts: [product && product.parts, Validators.required]
});
}
这会将更新的formControl / formGroup交给父级(它将被链接!)