我想编写一个包含Material Date Picker实现的组件,以简化在整个应用程序中使用日期组件的过程。我有一点工作,但混合模板驱动和反应形式代码,这从来都不是一个好主意,现在发出警告,它已被弃用。所以我试图只使用ngModel重写。但是,我无法使验证在初始加载时正常工作。它总是会产生必要的字段错误。
HTML
<mat-form-field style="width:inherit">
<input id="DatePickerControlInput" name="datePickerControlInput" #aocDatePickerControl="ngModel" (ngModelChange)="change($event)"
matInput [matDatepicker]="picker" [required]="required"
[placeholder]="label" [(ngModel)]="innerValue" (blur)="onBlur($event)" (dateChange)="onDateChange($event)" [max]="maxDate">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker></mat-datepicker>
<mat-error *ngIf="aocDatePickerControl.invalid && (aocDatePickerControl.dirty || aocDatePickerControl.touched)">
<div *ngIf="aocDatePickerControl.errors.required && !aocDatePickerControl.errors.matDatepickerParse">Required field</div>
<div *ngIf="aocDatePickerControl.errors.matDatepickerMax">Date cannot be in the future</div>
<div *ngIf="aocDatePickerControl.errors.matDatepickerParse">Not a valid date</div>
</mat-error>
</mat-form-field>
打字稿
import { Component, OnInit, OnChanges, forwardRef, HostBinding, Input, ViewChild, ElementRef } from '@angular/core';
import {
ControlValueAccessor, NG_VALUE_ACCESSOR, NG_VALIDATORS, FormControl,
Validator, Validators, ValidatorFn, AbstractControl, NgModel
} from '@angular/forms';
import * as moment from 'moment';
@Component({
selector: 'aoc-date-picker',
templateUrl: './CustomDatePicker.component.html',
providers: [
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => AocDatePickerComponent),
multi: true
},
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => AocDatePickerComponent),
multi: true
}
]
})
export class AocDatePickerComponent implements OnInit, OnChanges, ControlValueAccessor, Validator {
@ViewChild(NgModel) aocDatePickerControl: NgModel;
@ViewChild('aocDatePickerControl', { read: ElementRef }) inputControl: ElementRef;
@Input() label = 'Choose a date';
@Input() required?= false;
@Input() disabled?= false;
@Input() autofocus?= false;
@Input() allowFutureDates?= true;
maxDate;
innerValue;
onChange: any = () => { };
onTouched: any = () => { };
constructor() { }
focus() {
this.inputControl.nativeElement.focus();
}
ngOnInit() {
}
ngOnChanges() {
this.maxDate = this.allowFutureDates ? null : new Date();
}
writeValue(value: any) {
this.innerValue = value;
// this.aocDatePickerControl.control.setValue(this.innerValue);
// this.aocDatePickerControl.control.updateValueAndValidity();
// this.aocDatePickerControl.model = value;
// this.aocDatePickerControl.valueAccessor.writeValue(value);
}
// This needs to be wired to the dateChange event and not dateInput event so that
// the changed value is only bubbled up when the user changes focus or selects from
// the popup calendar and not on each key stroke
onDateChange(event) {
this.onChange(event.value);
}
registerOnChange(fn: (value: any) => void) {
this.onChange = fn;
}
registerOnTouched(fn: any) {
this.onTouched = fn;
}
setDisabledState(isDisabled: boolean) {
this.disabled = isDisabled;
if (isDisabled) {
this.aocDatePickerControl.control.disable();
} else {
this.aocDatePickerControl.control.enable();
}
}
validate(control: FormControl) {
const errors = Object.assign({}, this.aocDatePickerControl.errors || {});
return Object.keys(errors).length && this.aocDatePickerControl.invalid ? errors : null;
}
onBlur($event) {
if ($event.target && $event.target.value && $event.target.value.length === 8 && !isNaN($event.target.value)) {
const val: String = $event.target.value;
const month = val.slice(0, 2);
const day = val.slice(2, 4);
const year = val.slice(4);
this.innerValue = new Date(`${ month }/${ day }/${ year }`);
this.aocDatePickerControl.control.setValue(this.innerValue);
this.aocDatePickerControl.control.updateValueAndValidity();
this.onChange(this.innerValue);
}
if (this.aocDatePickerControl.hasError('matDatepickerParse')) {
this.aocDatePickerControl.control.setValue(null);
this.aocDatePickerControl.control.updateValueAndValidity();
}
this.onTouched();
}
}
答案 0 :(得分:0)
我在Material Github网站上发布了一个修复我的问题的问题。基本上,对于这样的事情,反应形式更好。这是评论和更新的stackblitz的链接。
在这种情况下,通过反应控制更容易处理状态:Updated StackBlitz