如果其他人遇到类似的情况,这是我想出的解决方案。我想从子表单控件元素动态创建表单控件模型。这样我就不必编写包含大量表单控制字段的初始模型,同时仍然可以获得反应式表单模型的好处。这是扩展 FormControlName 类的方法:
@Directive({
selector: '[hybridFormControl]'
})
class HybridFormControl Directive extends FormControlName implements ControlValueAccessor, OnChanges {
@Input('hybridFormControl') name: string;
onChange;
onTouched;
constructor(
@Optional() protected formGroupDirective: FormGroupDirective,
@Optional() @Self() @Inject(NG_VALUE_ACCESSOR) valueAccessors: ControlValueAccessor[],
private fb: FormBuilder,
private renderer: Renderer2,
private element: ElementRef
) {
super(formGroupDirective, [], [], valueAccessors, null);
this.valueAccessor = this;
}
ngOnChanges(changes: SimpleChanges): void {
if (!this._registered) {
// dynamically create the form control model on the form group model.
this.formGroup = this.formGroupDirective.form;
this.formGroup.registerControl(name, this.fb.control(''));
this._registered = true;
}
// IMPORTANT - this ties your extended form control to the form control
// model on the form group model that we just created above. Take a look
// at Angular github source code.
super.ngOnChanges(changes);
}
@HostListener('input', ['$event.target.value'])
@HostListener('change', ['$event.target.value'])
onInput(value): void {
this.onChange(modelValue);
}
writeValue(value): void {
const element = this.element.nativeElement;
this.renderer.setProperty(element, 'value', value);
}
registerOnChange(fn): void {
this.onChange = fn;
}
registerOnTouched(fn): void {
this.onTouched = fn;
}
}
您将使用这个新的混合指令,例如:
@Component({
selector: 'app',
template: `
<form formGroup=[formGroup]>
<input type="text" hybridFormControl="myName">
</form>
`
class AppComponent {
formGroup: FormGroup
constructor(fb: FormBuilder) {
this.form = this.fb.group({});
}
}
您将需要修改this.formGroup.registerControl(name, this.fb.control(''));
如果您想通过验证器,请添加一行代码。我尚未验证这一点,但希望这对遇到此问题的其他人有所帮助。
资料来源:https://github.com/angular/angular/blob/master/packages/forms/src/directives/reactive_directives/form_control_name.ts#L212 https://github.com/angular/angular/blob/master/packages/forms/src/directives/reactive_directives/form_control_name.ts#L212