简单地控制值访问器

时间:2019-06-20 06:27:04

标签: angular

什么是Angular的控制值访问器

我尝试了@input,@output方法,但是在验证过程中变得很复杂,尤其是对于ngModel

期望包含第3方UI控件的包装器组件可以轻松工作

2 个答案:

答案 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>创建输入。