为表单控件创建自定义物料日期选择器。要求是文本输入和日期选择都可以使用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 {
}
}