在过去的几个月里,ControlValueAccessors突然出现在我眼前,我对为什么或何时使用它们而不是在反应式表单中使用@Input
感到困惑。
这是到目前为止我如何使用响应式表单的示例代码:
@Component({
selector: 'app-my-component',
template: `<input [formControl]="form.get('specificControlName')" />`
// or the alternative method of [formGroup]="form" and formControlName="specificControlName"
})
export class MyComponent {
@Input() form: FormGroup; // passed in formGroup
ngOnInit() {
form.valueChanges.pipe(
// do rxjs magic here
).subscribe(value => {
// do something with the value
})
}
}
反应性表单保存表单的状态,因此即使从父组件中也可以访问该状态。我还可以访问所有不同的NgControl
属性,例如valid
,disabled
,dirty
和touched
。
ControlValueAccessors提供什么以使这种使用反应式表单的方式不起作用?在什么情况下,ControlValueAccessors通常比@Input
和@Output
更好地工作?
编辑:
https://medium.com/angular-in-depth/angular-nested-reactive-forms-using-cvas-b394ba2e5d0d
在本文中,作者提到了以下主要区别:
三种实现嵌套表单的方法:
...
- 通过Input将FormGroup的句柄传递给子组件,并在子模板中对其进行引用。有很多不错的教程。
但是使用这种方法的缺点是您将父表单组与子表单组紧密绑定。
- 使用复合CVA。
优点:高度可重用,便携式。更好的封装(父组件不一定需要组件的内部窗体控件)。当您有更多的表单模块(通常是一个大型项目)时,最好使用此方法。
缺点:需要在样板代码中实现CVA接口结果。
这很有趣,但是它引发了另外两个问题:为什么不让父母何时可以看到您的内部窗体控件?可移植性是什么意思?
也:
import { Component, OnInit } from '@angular/core';
import { ControlValueAccessor,NG_VALUE_ACCESSOR, NG_VALIDATORS, FormGroup,FormControl, Validator, Validators,AbstractControl, ValidationErrors } from "@angular/forms";
@Component({
selector: 'app-address-info',
templateUrl: './address-info.component.html',
styleUrls: ['./address-info.component.css']
})
export class AddressInfoComponent implements OnInit, ControlValueAccessor {
public addressForm: FormGroup = new FormGroup({
addressLine: new FormControl("",[Validators.required]),
areacode: new FormControl('', [Validators.required, Validators.maxLength(5)])
});
constructor() { }
ngOnInit() {
}
public onTouched: () => void = () => {};
writeValue(val: any): void {
val && this.addressForm.setValue(val, { emitEvent: false });
}
registerOnChange(fn: any): void {
console.log("on change");
this.addressForm.valueChanges.subscribe(fn);
}
registerOnTouched(fn: any): void {
console.log("on blur");
this.onTouched = fn;
}
setDisabledState?(isDisabled: boolean): void {
isDisabled ? this.addressForm.disable() : this.addressForm.enable();
}
}
当您将FormGroup
传递到ControlValueAccessor
组件时,作者正在使用与传递的对象相同的结构在组件内部初始化新的FormGroup
。那么,只传递FormGroup
本身不是更好吗?或封装有什么好处?
EDIT2:这是关于该主题的有趣视频:
答案 0 :(得分:0)
每当您使用本机HTML时,都使用Standard Reactive Form API 元素(输入,选择,按钮,表单等)
例如当您必须使用自定义时使用ControlValueAccessor HTML元素(即mat-list,mat-table,ag-grid-table等), 原因是因为它是一个接口,充当了之间的桥梁 角形API和DOM元素。 ControlValueAccessor example