繁体   English   中英

如何在自定义ControlValueAccessor中更新ng-pristine

[英]How to update ng-pristine in Custom ControlValueAccessor

我编写了一个简单的CustomValueAccessor来实现pikaday datepicker。 它可以工作,但是当我使用日期选择器选择日期并更新属性时,内部输入控件(通过ngModel绑定到属性)不会更新其ng-pristine类,而外部组件却可以。 我需要将内部输入标记为ng-touched,但我不知道如何实现。

这是我的课:

import { Component, OnInit, Input, Output, EventEmitter, ViewEncapsulation, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

import { DateService } from "./shared";

import * as pikaday from 'pikaday'

@Component({
  selector: 'datepicker',
  templateUrl: 'datepicker.component.html',
  styles: [require('pikaday/css/pikaday.css')],
  encapsulation: ViewEncapsulation.None,
    providers: [
    // providers to implement formControlName
    { 
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => DatePickerComponent),
      multi: true
    }
  ]
})
export class DatePickerComponent implements OnInit, ControlValueAccessor {

  /**
   * ID of the input element
   */
  @Input() id: string;

  /**
   * The minimum date the user can select. Defaults to today. Set to null to not require. 
   */
  @Input() minDate: Date = new Date();

  /**
   * Outputs the chosen date string
   */
  @Output('date') dateChanged: EventEmitter<string> = new EventEmitter<string>();

  /**
   * The formatted date value
   */
  private _date: string;

  constructor() { }

  /**
   * Initialises the pikaday datepicker
   */
  ngOnInit() {
    if(!this.id)
      throw "Id is required for datepicker"

    let options = { 
      field: document.getElementById(this.id),
      format: DateService.datePickerFormat,
      onSelect: date => {
        this.date = startDatePicker.toString();
      } 
    };
    if(this.minDate)
      options['minDate'] = this.minDate;

    let startDatePicker = new pikaday(options);
  }

  /**
   * Emits the new date
   */
  set date(value){
    this._date = value;
    this.onChangeCallback(value);
    this.onTouchedCallback(value);
  }

  /**
   * Returns the date value
   */
  get date(){
    return this._date;
  }

  /**
   * Push date to parent components (required by ControlValueAccessor)
   */
  onChangeCallback = (_: any) => {};

  /**
   * let formControlValue interface register a touch callback 
   */
  onTouchedCallback = (_: any) => {};

  /**
   * Allows parent component to set the onchange handler
   */
  registerOnChange(fn) {
    this.onChangeCallback = fn;
  }

  /**
   * Allows parent component to set an ontouch handler (not implemented)
   */
  registerOnTouched(fn) {
    this.onTouchedCallback = fn;
  }

  /**
   * Called when the component is inited with formControlName
   */
  writeValue(value: any) {
    this.date = value;
  }

}

和模板:

<input type="text" [id]="id" [(ngModel)]="date">

这是在使用datepicker设置值之前的HTML:

<datepicker formcontrolname="endDatePicker" id="endDatePicker" ng-reflect-id="endDatePicker" ng-reflect-name="endDatePicker" class="ng-untouched ng-pristine ng-invalid"><input type="text" ng-reflect-model="" ng-reflect-id="endDatePicker" id="endDatePicker" class="ng-untouched ng-pristine ng-valid">
    <input type="text" ng-reflect-model="" ng-reflect-id="endDatePicker" id="endDatePicker" class="ng-untouched ng-pristine ng-valid">
</datepicker>

然后是这里:

<datepicker formcontrolname="endDatePicker" id="endDatePicker" ng-reflect-id="endDatePicker" ng-reflect-name="endDatePicker" class="ng-touched ng-dirty ng-valid"><input type="text" ng-reflect-model="19 October, 2016" ng-reflect-id="endDatePicker" id="endDatePicker" class="ng-pristine ng-valid ng-touched">
    <input type="text" ng-reflect-model="19 October, 2016" ng-reflect-id="endDatePicker" id="endDatePicker" class="ng-pristine ng-valid ng-touched">
</datepicker>

注意输入控件上的类:ng-pristine和ng-touched。 就我而言,它应该是ng-dirty,而不是ng-pristine。

您可以使用ngControl.control属性,从实现ControlValueAccessor本身的组件中将控件标记为原始(或脏的,触摸的,未触摸的):

export class DatePickerComponent implements ControlValueAccessor {

  // ...
  yourFunction(): void {

    let control = this.ngControl.control;

    // use any of these to manipulate the state of the control in the form
    control.markAsTouched();
    control.markAsUntouched();
    control.markAsDirty();
    control.markAsPristine();
  }
}

ngControl.controle是Angular形式在内部使用的AbstractControl对象。 一些文档链接: https : //angular.io/api/forms/AbstractControl

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM