我将Angular Control值访问器接口用于项目中的可重用表单。而且我在构建父表单时遇到设置值的问题。
假设我有一个Address对象,我想将其映射到cva表单中,并且此对象具有比实际表单更多的字段。 因此,在父组件中,我构建了表单:
constructor(private formBuilder: FormBuilder) {
const address = new Address({
id: 1,
city: 'Roma',
streetAddress: 'via Roma',
houseNumber: '12b',
postalCode: 43213,
addressType: 'abitazione',
addInfo: 'primo piano'
});
this.addressForm = this.formBuilder.group({
address: [address],
});
}
<form [formGroup]="addressForm" (ngSubmit)="submit()">
<app-address-cva formControlName="address"></app-address-cva>
<button>Sign Up</button>
</form>
在子组件中,我处理父组件传递的值:
writeValue(value: Address) {
if (value) {
this.value = value;
}
if (value === null) {
this.form.reset();
}
}
set value(value) {
this.cityControl.setValue(value.city);
this.streetAddressControl.setValue(value.streetAddress);
this.houseNumberControl.setValue(value.houseNumber);
this.postalCodeControl.setValue(value.postalCode);
this.onChange(value);
this.onTouched();
}
提交表单时,我没有得到子cva表单的值,而是得到了父级传递的地址对象。如果表单字段未被用户触摸,则属于这种情况。如果子窗体的任何输入被触摸,则子窗体将返回窗体控件的值,并且一切正常。
我尝试使用更改检测,在writeValue方法中以编程方式将cva表单文件标记为已触摸且脏了,我甚至尝试调用updateValueAndValidity({onlySelf:false,酋长:true})方法。但是我无法解决这个问题。
这里是stackblitz项目,用于显示确切的问题: [https://stackblitz.com/edit/angular-ggepd6?file=src%2Fapp%2Fapp.component.ts]
如果有人可以帮助我解决这个问题,我将不胜感激。
答案 0 :(得分:0)
您可以执行以下操作来强制使用第一个值:
import {startWith} from 'rxjs/operators';
registerOnChange(fn) {
this.form.valueChanges.pipe(startWith(this.form.value)).subscribe(fn);
}
当您尝试以这种方式处理表单时,变更检测有一种与您不利的习惯,尽管并非不可能。问题是更改检测从父级到子级(单向流)起作用,而不是相反。