什么是Angular的控制值访问器
我尝试了@input,@output方法,但是在验证过程中变得很复杂,尤其是对于ngModel
期望包含第3方UI控件的包装器组件可以轻松工作
答案 0 :(得分:1)
简单的“好的控制值访问器”: 目的:拥有一个自定义的UI子组件,该组件是使用第三方UI小部件的包装器,例如ngx-bootstrap的DatePicker PrimeNg。包装器可以轻松地与Form控件(父组件)同步,而不必使用@ Inputs / Outputs。主要是,您如何否则将有效通知父母。轻松通过CVA。
示例: 假设您想像这样从ngx-bootstrap构建日期选择器: 假设您有一个使用自定义DatePicker的表单:
Form.ts:
currentDate: Date = new Date();
onDateChanged($event){
// do something with the received date..Maybe call an api for the selectedDate's data
}
Form.html:
<custom-date-picker id="selectedDate" name="fieldName" [(ngModel)]="currentDate" (onDateChanged)="onDateChanged($event)"></custom-date-picker>
创建一个包装器组件: CustomDatePicker.ts:
@Component({
selector: 'custom-date-picker',
templateUrl: 'custom-date-picker.component.html',
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => IpxDatePickerComponent),
multi: true
}
]
})
export class CustomDatePickerComponent implements ControlValueAccessor {
onChanged: any = () => {};
// tslint:disable-next-line:no-empty
onTouched: any = () => {};
writeValue(obj: any): void {
if (obj) {
this.selectDate(obj);
}
}
registerOnChange(fn: any): void {
this.onChanged = fn;
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
// tslint:disable-next-line:no-empty
setDisabledState?(isDisabled: boolean): void {}
selectDate(val): void {
this.selectedDate = val;
}
dateChanged = (e: Date): void => {
if (e) {
this.onChanged(e);// this statement should have ideally set your parent forms ngModel variable to the new selected date.
this.onDateChanged.emit(e);
}
};
}
CustomDatePicker.html:
<input type="text" #datePicker="bsDatepicker" placeholder="Datepicker" (bsValueChange)="dateChanged($event)" [(ngModel)]="selectedDate" [bsConfig]="bsConfig" />
就这样,现在,如果您看到的话,表单的ngModel将同步。子控件和父控件也将与selectedDate以及触摸之类的验证同步。
我实际上发现这种方法很有用,因为在使用常规@ inputs,@ outputs实施时发现了很多同步问题。
我们现在甚至可以使用CVA来使用它们,但是它们将主要用于操纵其他数据,而不是包装器目的(在这种情况下为日期)
答案 1 :(得分:0)
简单来说,ControlValueAccessor
是将ngModel
/ formControl
添加到任何HTML元素而不仅仅是表单控件的一种方式。
它仅依赖于几种方法,所有方法都在the documentation中进行了说明。
例如,您可以将多个控件组合为一个,或在contenteditable
元素上使用<p>
创建输入。