Я создал пользовательский компонент DatePicker, используя Angular Material, MomentDateAdapter и ControlValueAccessor.
Форматирование даты и валидность обрабатываются MomentDateAdapter.
Мне нужно получить значение валидности, которое обрабатывается адаптером.
То, что я пробовал:
- Получение доступа к элементу ввода:
@ViewChild('input') input: ElementRef
Но я не смог найдите там что-нибудь полезное, когда дата недействительна (больше, чем maxDate):
this.input.nativeElement.validity
показывает, что она действительна:
Доступ к объекту момента, также действительный:
Где я могу найти значение достоверности, к которому у адаптера есть доступ?
date-picker.component.ts
import { Component, Injector, Input, OnInit, Self, Output, EventEmitter, ViewChild, ElementRef } from '@angular/core';
import { ControlValueAccessor, NgControl } from '@angular/forms';
import { getUTCDate } from '../../services/util.service';
import { MomentDateAdapter, MAT_MOMENT_DATE_ADAPTER_OPTIONS } from '@angular/material-moment-adapter';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE, } from '@angular/material/core';
import _moment from 'moment'
// tslint:disable-next-line:no-duplicate-imports
import { default as _rollupMoment } from 'moment'
const moment = _rollupMoment || _moment
export const MY_FORMATS = {
parse: {
dateInput: 'DD.MM.YYYY',
},
display: {
dateInput: 'DD.MM.YYYY',
monthYearLabel: 'MMM YYYY',
dateA11yLabel: 'LL',
monthYearA11yLabel: 'MMMM YYYY',
},
};
@Component({
selector: 'app-date-picker',
templateUrl: './date-picker.component.html',
styleUrls: ['./date-picker.component.scss'],
providers: [
{ provide: MAT_DATE_FORMATS, useValue: MY_FORMATS },
{
provide: DateAdapter,
useClass: MomentDateAdapter,
deps: [MAT_DATE_LOCALE, MAT_MOMENT_DATE_ADAPTER_OPTIONS],
},
{ provide: MAT_MOMENT_DATE_ADAPTER_OPTIONS, useValue: { useUtc: true } },
{ provide: MAT_DATE_FORMATS, useValue: MY_FORMATS },
]
})
export class DatePickerComponent implements ControlValueAccessor, OnInit {
constructor(
private injector: Injector,
@Self() private readonly ngControl: NgControl) {
this.ngControl = this.injector.get(NgControl);
this.ngControl.valueAccessor = this;
}
@ViewChild('input') input: ElementRef
isOpen = false;
@Input() id;
@Input() class: string;
@Input() placeholder = 'Select Date';
@Input('date') _date: Date;
@Input() setMaxDate: boolean;
@Output() blur: EventEmitter<Date> = new EventEmitter<Date>();
onChange: any = () => {
};
onTouched: any = () => {
};
get required() {
return this._required;
}
set required(req) {
this._required = coerceBooleanProperty(req);
}
private _required = false;
public valid: boolean = true;
maxDate = getUTCDate(moment());
ngOnInit(): void {
if (!this.setMaxDate) {
this.maxDate = null;
}
this.ngControl.control.statusChanges.subscribe((status) => {
if (this.ngControl.control.errors) {
this.required = (this.ngControl.control.errors.required);
} else {
this.required = false;
}
});
}
get date() {
return this._date;
}
set date(val) {
this.valid = !!val
this._date = val;
this.onChange(val);
this.onTouched();
}
writeValue(value): void {
if (value) {
this.date = value;
}
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
setDisabledState?(isDisabled: boolean): void {
throw new Error('Method not implemented.');
}
toggle(event) {
this.isOpen = !this.isOpen;
}
close() {
this.isOpen = false;
}
selectDate(event: Date) {
this.date = event;
this.close();
}
onBlur(){
this.blur.emit(this.date)
}
}