角度:ControlValueAccessor与@Input-何时对表单使用什么?

时间:2019-11-26 11:19:51

标签: angular

在过去的几个月里,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. 通过Input将FormGroup的句柄传递给子组件,并在子模板中对其进行引用。有很多不错的教程。
  2.   
     

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

     
      
  1. 使用复合CVA。
  2.   
     

优点:高度可重用,便携式。更好的封装(父组件不一定需要组件的内部窗体控件)。当您有更多的表单模块(通常是一个大型项目)时,最好使用此方法。

     

缺点:需要在样板代码中实现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:这是关于该主题的有趣视频:

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

1 个答案:

答案 0 :(得分:0)

  

每当您使用本机HTML时,都使用Standard Reactive Form API   元素(输入,选择,按钮,表单等)

     

例如当您必须使用自定义时使用ControlValueAccessor   HTML元素(即mat-list,mat-table,ag-grid-table等),   原因是因为它是一个接口,充当了之间的桥梁   角形API和DOM元素。 ControlValueAccessor example