Angular: ControlValueAccessor vs @Input - 何时对表单使用什么? 在过去的几个月



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属性,如validdisableddirtytouched

ControlValueAccessors 提供了这种使用响应式表单的方式所没有的什么?在哪些用例中,ControlValueAccessors比@Input@Output更好?

编辑

https://medium.com/angular-in-depth/angular-nested-reactive-forms-using-cvas-b394ba2e5d0d

在本文中,作者提到了以下主要区别:

实现嵌套表单的三种方法:

  1. 通过输入将 FormGroup 的句柄传递给子组件,并在子模板中引用它。上面有几个很好的教程。

但是使用这种方法的缺点是,您将父窗体组与子组的窗体组紧密绑定。

  1. 使用复合 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本身不是更好吗?或者封装有什么好处?

编辑2:这是一个关于这个主题的有趣视频:

https://www.youtube.com/watch?v=CD_t3m2WMM8

每当使用本机 HTML 时,请使用标准反应式表单 API 元素(输入、选择、按钮、表单等(

例如,当您必须使用自定义时,请使用 ControlValueAccessor HTML 元素(即 mat-list、mat-table、ag-grid-table 等(, 原因是因为它是一个充当Angular 形成 API 和 DOM 元素。控件值访问器示例

最新更新