自定义MatDatePicker

时间:2019-02-21 20:55:27

标签: angular

为表单控件创建自定义物料日期选择器。要求是文本输入和日期选择都可以使用moment.js来验证日期。当前,除了输入日期时,所有其他功能均有效,日期会自动显示。寻找使用两种方法,一种用于文本输入,另一种用于mat-datepicker元素。有自定义表单控制经验的任何人,请提出建议。

**更新:只有在完全输入键入日期后,才需要为方法addEvent触发事件

datepicker.html

      <div class="form-inline">
        <input matInput [matDatepicker]="picker"
               [value]="dateValue"
               [min]="minDate"
               [max]="maxDate"
               [style.width]="inputWidth"
               class="form-control"
               [textMask]="{mask: maskDateNum}"
               autocomplete="off"
               (dateInput)="addEvent('input', $event)"
               [placeholder]="placeholder">


        <mat-icon
          id="clear-btn"
          *ngIf="!disabled && (dateValue != null)"
          (click)="clearDate()" >clear</mat-icon>
      <mat-icon
        *ngIf="disabled || (dateValue == null)"></mat-icon>
      <mat-datepicker-toggle matSuffix [hidden]="disabled" [for]="picker"></mat-datepicker-toggle>
      <mat-datepicker #picker></mat-datepicker>
      <p *ngIf="!isInputValid()">Input is invalid</p>
    </div>

datepicker.ts

export class DatePicker implements ControlValueAccessor, Validator, OnInit {
  @Input() disabled = false;
  @Input() required = false;
  @Input() minDate = null;
  events: string[] = [];
  @Input() maxDate = null;
  @Input() public inputWidth = '120px';
  maskDateNum: any[] = [/\d/, /\d/, '/', /\d/, /\d/, '/', /\d/, /\d/, /\d/, /\d/];


  /**
   * Set the value of the date set by user, notice the underscore infront of the datevalue
   */

  @Input() _dateValue: string = null;

  /**
   * Placeholder value for the material control input
   */
  @Input() public placeholder: string = null;

  /**
   * The date format to use with default format but allowing you to pass a custom date format
   */
  @Input() private format = 'YYYY-MM-DD';
  private inFormat = 'M/D/YYYY';
  private orFormat = 'YYYY-MM-DD';
  /**
   * setting matFormField to true wraps the input in a matformfield
   */
  @Input() matFormField = false;

  @Output()
  change = new EventEmitter();

  get dateValue() {
    const v = moment(this._dateValue, this.inFormat);
    if (this._dateValue === 'Invalid date' || !v.isValid()) {
      return null;
    }
    if (v.isValid() && v.format(this.format) !== 'Invalid date') {
      return v;
    }
    return null;
  }

  set dateValue(val) {
    if (moment(val).format(this.inFormat) === 'Invalid date') {
      this._dateValue = null;
    } else {
      this._dateValue = moment(val).format(this.inFormat);
    }

    this.propagateChange(this._dateValue);
  }

  addEvent(type: string, event: MatDatepickerInputEvent<Date>) {
    if (event.value === null) {
      this.dateValue = null;
    }
    if (event.value.toString().length > 8) {
      this.dateValue = moment(event.value, this.orFormat);
    }
  }


  writeValue(value: any) {
    if (value !== undefined && value !== null) {
      this.dateValue = moment(value, this.inFormat);
    }
    if (value === null) {
      this.dateValue = null;
    }
  }

  propagateChange = (_: any) => {
    this.change.emit();
  }

  registerOnChange(fn) {
    this.propagateChange = fn;
  }

  registerOnTouched() {
  }

  clearDate() {
    this.dateValue = null;
  }

  registerOnValidatorChange(fn: () => void): void {
  }

  setDisabledState(isDisabled: boolean): void {
  }

  validate(control: AbstractControl): ValidationErrors | null {
    const val = control.value;
    console.log(val);
    if ((val == null || val == undefined || val == 'Invalid date' || val == '') && this.required) {
      return {
        required: true
      };
    }
    return null;
  }


  isInputValid(): boolean {
    return this.validate(new FormControl(
      this.dateValue
    )) === null;

  }

  ngOnInit(): void {

  }
}

0 个答案:

没有答案