[英]reusable angular reactive form (ControlValueAccessor) & material stepper & asynchronous validation
[英]Angular: composite ControlValueAccessor to implement nested form
在Angular Connect 2017演示文稿中引入了用于实现嵌套表单的ControlValueAccessor的组合。
在本演示中,演讲者展示了一种实现自定义表单控件的方法,该表单控件具有多个值(不仅是单个字符串值,而且还有两个字符串字段,如街道和城市)。 我想实现它,但我被卡住了。 示例应用程序在这里,是否有人知道我应该纠正什么?
https://stackblitz.com/edit/angular-h2ehwx
父组件
@Component({
selector: 'my-app',
template: `
<h1>Form</h1>
<form [formGroup]="form" (ngSubmit)="onSubmit(form.value)" novalidate>
<label>name</label>
<input formControlName="name">
<app-address-form formControlName="address"></app-address-form>
<button>submit</button>
</form>
`,
})
export class AppComponent {
@Input() name: string;
submitData = '';
form: FormGroup;
constructor(private fb: FormBuilder) {
this.form = fb.group({
name: 'foo bar',
address: fb.group({
city: 'baz',
town: 'qux',
})
});
}
onSubmit(v: any) {
console.log(v);
}
}
嵌套表单组件
@Component({
selector: 'app-address-form',
template: `
<div [formGroup]="form">
<label>city</label>
<input formControlName="city" (blur)="onTouched()">
<label>town</label>
<input formControlName="town" (blur)="onTouched()">
</div>
`,
providers: [
{
provide: NG_VALUE_ACCESSOR,
multi: true,
useExisting: forwardRef(() => AddressFormComponent)
}
]
})
export class AddressFormComponent implements ControlValueAccessor {
form: FormGroup;
onTouched: () => void = () => {};
writeValue(v: any) {
this.form.setValue(v, { emitEvent: false });
}
registerOnChange(fn: (v: any) => void) {
this.form.valueChanges.subscribe(fn);
}
setDisabledState(disabled: boolean) {
disabled ? this.form.disable() : this.form.enable();
}
registerOnTouched(fn: () => void) {
this.onTouched = fn;
}
}
和我得到的错误信息
ERROR TypeError: Cannot read property 'setValue' of undefined
at AddressFormComponent.writeValue (address-form.component.ts:32)
at setUpControl (shared.js:47)
at FormGroupDirective.addControl (form_group_directive.js:125)
at FormControlName._setUpControl (form_control_name.js:201)
at FormControlName.ngOnChanges (form_control_name.js:114)
at checkAndUpdateDirectiveInline (provider.js:249)
at checkAndUpdateNodeInline (view.js:472)
at checkAndUpdateNode (view.js:415)
at debugCheckAndUpdateNode (services.js:504)
at debugCheckDirectivesFn (services.js:445)
我认为FormGroup实例应该以某种方式注入嵌套表单组件......
在您的AppComponent
几个问题更改为您的FormBuilder
:
this.form = fb.group({
name: 'foo bar',
address: fb.control({ //Not using FormGroup
city: 'baz',
town: 'qux',
})
});
在您的AddressFormComponent
您需要像这样初始化FormGroup:
form: FormGroup = new FormGroup({
city: new FormControl,
town: new FormControl
});
这是您的示例的分支: https : //stackblitz.com/edit/angular-np38bi
我们(在工作中)遇到了这个问题并且在几个月内尝试了不同的事情:如何正确处理嵌套表单。
事实上, ControlValueAccessor
似乎是要走的路,但我们发现它非常冗长,构建嵌套表单的时间很长。 由于我们在应用程序中使用了这种模式,我们最终花了一些时间进行调查并尝试提出更好的解决方案。 我们称它为ngx-sub-form
,它是NPM上的repo(+ Github上的源代码)。
基本上,要创建子表单,您只需扩展我们提供的类,并传递FormControls。 而已。
我们已经更新了我们的代码库以使用它,我们非常高兴它,所以你可能想试试看看它是怎么回事:)
PS:我们还有一个完整的演示在这里运行https://cloudnc.github.io/ngx-sub-form
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.