gp-crm-ui
Version:
Модуль компонентов UI Имя модуля: `gp-crm-ui`
183 lines (155 loc) • 4.44 kB
text/typescript
import {
OverlayOrigin,
OverlayRef
} from '@angular/cdk/overlay';
import {
Component,
EventEmitter,
forwardRef,
HostBinding,
HostListener,
Input,
OnDestroy,
OnInit,
ViewChild
} from '@angular/core';
import {
ControlValueAccessor,
NG_VALUE_ACCESSOR
} from '@angular/forms';
import {
format,
parse
} from 'date-fns';
import * as ru from 'date-fns/locale/ru';
// Компоненты
import { CrmDatepickerPopupComponent } from '../../components/crm-datepicker-popup/crm-datepicker-popup.component';
// Сервисы
import { CrmContextMenuOverlayService } from '../../services';
// Выбор даты
export class CrmDatepickerComponent implements
OnInit, OnDestroy, ControlValueAccessor {
constructor(private readonly contextMenuOverlay: CrmContextMenuOverlayService) {
this.DATA.select.subscribe((date: Date) => {
this.date = date;
});
}
// Флаг наличия ошибки
public hasError: boolean;
// Заглушка поля
public placeholder: string;
// Ссылка на поле ввода
private readonly popupOrigin: OverlayOrigin;
// Конфигурация всплывающего окна
private readonly CONFIG = {
elementRef: null,
overlayComponent: CrmDatepickerPopupComponent,
origin: { originX: 'start', originY: 'bottom' },
overlay: { overlayX: 'start', overlayY: 'top' }
};
// Данные календаря
private readonly DATA = {
selected: null,
select: new EventEmitter<Date>()
};
// Вызовем когда значение изменится
private onChange: (value: Date) => void;
// Вызовем при любом дествии пользователя с контроллом
private onTouched: () => void;
// Дата
public _date: Date;
public get date(): Date {
return this._date;
}
public set date(value: Date) {
this._date = value;
this.DATA.selected = value;
this.text = value && format(value, 'DD.MM.YYYY', { locale: ru });
if (this.onChange) {
this.onChange(value);
}
}
// Поле ввода
public text: string;
// Флаг, отключено
public disabled: boolean = false;
// Ссылка на календарь
private overlayRef: OverlayRef;
// Открыть окно
private open(): void {
if (
!(this.overlayRef && this.overlayRef.hasAttached()) &&
!this.disabled
) {
this.overlayRef = this.contextMenuOverlay.open(this.CONFIG, this.DATA);
}
}
// Закрыть окно
private close(): void {
if (this.overlayRef) { this.overlayRef.dispose(); }
this.overlayRef = null;
}
// Реакция на клик хост-элемента
public onClick(): void {
if (this.onTouched) {
this.onTouched();
}
}
// Открыть/скрыть календаь
public onToggle(): void {
if (this.overlayRef && this.overlayRef.hasAttached()) {
this.close();
} else {
this.open();
}
}
// Обработчик заполнености маски
public onCompleteMask(isCompleted: boolean): void {
this.date = isCompleted
? parse(
this.text
.split('.')
.reverse()
.join('-')
)
: null;
}
// --------------------------------------------------------------------------
// Вызовет форма, если значение изменилось извне
public writeValue(date: Date): void {
this.date = date;
}
// Сохраняем обратный вызов для изменений
public registerOnChange(fn: any): void {
this.onChange = fn;
}
// Сохраняем обратный вызов для "касаний"
public registerOnTouched(fn: any): void {
this.onTouched = fn;
}
// Установка состояния disabled
public setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled;
}
// --------------------------------------------------------------------------
// HOOKS
// Инициализация
public ngOnInit(): void {
this.CONFIG.elementRef = this.popupOrigin.elementRef;
}
// Уничтожение
public ngOnDestroy(): void {
this.close();
}
}