File

projects/rebirth-ng/src/lib/date-picker/date-picker.directive.ts

Implements

OnInit ControlValueAccessor OnDestroy

Metadata

providers { : , : (() => ), : true }
selector [reDatePicker]

Index

Properties
Methods
Inputs
HostListeners

Constructor

constructor(elementRef: ElementRef, viewContainerRef: ViewContainerRef, componentFactoryResolver: ComponentFactoryResolver, renderer: Renderer2, injector: Injector, positionService: PositionService, rebirthNGConfig: RebirthNGConfig)
Parameters :
Name Type Optional
elementRef ElementRef no
viewContainerRef ViewContainerRef no
componentFactoryResolver ComponentFactoryResolver no
renderer Renderer2 no
injector Injector no
positionService PositionService no
rebirthNGConfig RebirthNGConfig no

Inputs

appendBody

Default value: false

cssClass

Type: string

dateConverter

Type: DateConverter

dateFormat

Type: string

disabled

Default value: false

locale

Type: string

maxDate
minDate
placement

Type: "top" | "top-left" | "top-right" | "bottom" | "bottom-left" | "bottom-right"

Default value: 'bottom-left'

selectedDate

Type: Date

showTimePicker

Type: boolean

HostListeners

blur
Arguments : '$event'
blur()
change
Arguments : '$event'
change($event: )
document:click
Arguments : '$event'
document:click($event: Event)
keyup.esc
Arguments : '$event'
keyup.esc()

Methods

Private applyPopupStyling
applyPopupStyling(nativeElement: any)
Parameters :
Name Type Optional
nativeElement any no
Returns : void
Private fillPopupData
fillPopupData()
Returns : void
Private getDateFormat
getDateFormat()
Returns : any
hide
hide()
Returns : void
ngOnDestroy
ngOnDestroy()
Returns : void
ngOnInit
ngOnInit()
Returns : void
registerOnChange
registerOnChange(fn: any)
Parameters :
Name Type Optional
fn any no
Returns : void
registerOnTouched
registerOnTouched(fn: any)
Parameters :
Name Type Optional
fn any no
Returns : void
Private removePopView
removePopView()
Returns : void
setDisabledState
setDisabledState(isDisabled: boolean)
Parameters :
Name Type Optional
isDisabled boolean no
Returns : void
show
show()
Returns : void
toggle
toggle($event: Event)
Parameters :
Name Type Optional
$event Event no
Returns : void
Private writeModelValue
writeModelValue(selectDate: Date)
Parameters :
Name Type Optional
selectDate Date no
Returns : void
writeValue
writeValue(obj: any)
Parameters :
Name Type Optional
obj any no
Returns : void

Properties

Private _dateFormat
_dateFormat: string
Type : string
Private _maxDate
_maxDate: Date
Type : Date
Private _minDate
_minDate: Date
Type : Date
Private cmpRef
cmpRef: ComponentRef<DatePickerPopupComponent>
Type : ComponentRef<DatePickerPopupComponent>
dateConfig
dateConfig: any
Type : any
isOpen
isOpen:
Default value : false
Private lastEventTarget
lastEventTarget: any
Type : any
Private onChange
onChange:
Default value : (_: any) => null
Private onTouched
onTouched:
Default value : () => null

Accessors

maxDate
getmaxDate()
setmaxDate(date: )
Parameters :
Name Optional
date no
Returns : void
minDate
getminDate()
setminDate(date: )
Parameters :
Name Optional
date no
Returns : void
dateFormat
getdateFormat()
setdateFormat(dateFormat: string)
Parameters :
Name Type Optional
dateFormat string no
Returns : void
import {
  ComponentFactoryResolver, ComponentRef, Directive, ElementRef, forwardRef, HostListener, Injector, Input, OnInit,
  Renderer2,
  ViewContainerRef, OnDestroy
} from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { PositionService } from '../position/positioning.service';
import { DatePickerPopupComponent } from './date-picker-popup.component';
import { SelectDateChangeEventArgs, SelectDateChangeReason } from './date-change-event-args.model';
import { RebirthNGConfig } from '../rebirth-ng.config';
import { DateConverter } from '../utils/date-converter';
import { DefaultDateConverter } from '../utils/default-date-converter';

@Directive({
  selector: '[reDatePicker]',
  exportAs: 'datePicker',
  providers: [{
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => DatePickerDirective),
    multi: true
  }]
})
export class DatePickerDirective implements OnInit, ControlValueAccessor, OnDestroy {
  @Input() placement: 'top' | 'top-left' | 'top-right' | 'bottom' | 'bottom-left' | 'bottom-right' = 'bottom-left';
  @Input() selectedDate: Date;
  @Input() locale: string;
  @Input() showTimePicker: boolean;
  @Input() cssClass: string;
  @Input() disabled = false;
  @Input() dateConverter: DateConverter;
  @Input() appendBody = false;
  isOpen = false;
  dateConfig: any;
  private _dateFormat: string;
  private _maxDate: Date;
  private _minDate: Date;
  private lastEventTarget: any;
  private cmpRef: ComponentRef<DatePickerPopupComponent>;
  private onChange = (_: any) => null;
  private onTouched = () => null;

  constructor(private elementRef: ElementRef, private viewContainerRef: ViewContainerRef,
              private componentFactoryResolver: ComponentFactoryResolver, private renderer: Renderer2,
              private injector: Injector, private positionService: PositionService,
              private rebirthNGConfig: RebirthNGConfig) {

    this.dateConfig = rebirthNGConfig.datePicker;
    this.dateConverter = rebirthNGConfig.datePicker.dateConverter || new DefaultDateConverter();
    this.showTimePicker = rebirthNGConfig.datePicker.timePicker;
    this.locale = rebirthNGConfig.datePicker.locale;
    this._minDate = new Date(this.dateConfig.min, 0, 1, 0, 0, 0);
    this._maxDate = new Date(this.dateConfig.max, 11, 31, 23, 59, 59);
  }

  @Input()
  set maxDate(date: Date | any) {
    const parseDate = this.dateConverter.parse(date, this.getDateFormat(), this.locale);
    if (parseDate) {
      this._maxDate = parseDate;
    }
  }

  get maxDate() {
    return this._maxDate;
  }

  @Input()
  set minDate(date: Date | any) {
    const parseDate = this.dateConverter.parse(date, this.getDateFormat(), this.locale);
    if (parseDate) {
      this._minDate = parseDate;
    }
  }

  get minDate() {
    return this._minDate;
  }

  @Input()
  set dateFormat(dateFormat: string) {
    if (dateFormat && this._dateFormat !== dateFormat) {
      this._dateFormat = dateFormat;
      this.writeModelValue(this.selectedDate);
    }
  }

  get dateFormat() {
    return this._dateFormat;
  }

  ngOnInit() {
    const factory = this.componentFactoryResolver.resolveComponentFactory(DatePickerPopupComponent);
    const viewContainerRef = this.appendBody ? this.rebirthNGConfig.rootContainer : this.viewContainerRef;
    // EXCEPTION: Expression has changed after it was checked when append to body;
    setTimeout(() => {
      this.cmpRef = <ComponentRef<DatePickerPopupComponent>>viewContainerRef
        .createComponent(factory, viewContainerRef.length, this.injector);
      this.applyPopupStyling(this.cmpRef.location.nativeElement);
      const component = this.cmpRef.instance;
      this.hide();
      component.writeValue(this.selectedDate);
      this.fillPopupData();
      component.ngOnInit();

      component.registerOnChange((selectedDate) => {
        this.writeValue(selectedDate);
        this.onChange(selectedDate);
      });

      component.selectedDateChange.subscribe((arg: SelectDateChangeEventArgs) => {
        if (arg.reason === SelectDateChangeReason.date) {
          this.hide();
        }
      });
    }, 0);
  }

  writeValue(obj: any): void {
    this.selectedDate = obj ? this.dateConverter.parse(obj, this.getDateFormat(), this.locale) : null;
    this.writeModelValue(this.selectedDate);
  }

  registerOnChange(fn: any): void {
    this.onChange = fn;
  }

  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }

  setDisabledState(isDisabled: boolean): void {
    this.disabled = isDisabled;
    this.renderer.setProperty(this.elementRef.nativeElement, 'disabled', isDisabled);
    if (this.isOpen) {
      this.cmpRef.instance.setDisabledState(isDisabled);
    }
  }

  toggle($event: Event) {
    this.lastEventTarget = $event.target;
    if (this.isOpen) {
      this.hide();
      return;
    }

    this.show();
  }

  @HostListener('document:click', ['$event'])
  onDocumentClick($event: Event) {
    const hostElement = this.elementRef.nativeElement;
    if ([hostElement, this.lastEventTarget].indexOf($event.target) === -1) {
      this.hide();
    }
  }

  show() {
    const component = this.cmpRef.instance;
    component.writeValue(this.selectedDate);
    this.fillPopupData();
    this.isOpen = true;
    const targetElement = this.cmpRef.location.nativeElement;
    const hostElement = this.elementRef.nativeElement;
    this.renderer.setStyle(targetElement, 'display', 'inline-block');
    const clientRect = this.positionService.positionElements(hostElement, targetElement, this.placement, this.appendBody);
    this.renderer.setStyle(targetElement, 'left', `${clientRect.left}px`);
    this.renderer.setStyle(targetElement, 'top', `${clientRect.top}px`);
  }

  hide() {
    if (this.cmpRef) {
      this.isOpen = false;
      const target = this.cmpRef.location.nativeElement;
      this.renderer.setStyle(target, 'display', 'none');
    }
  }

  @HostListener('blur', ['$event'])
  onBlur() {
    this.onTouched();
  }

  @HostListener('change', ['$event'])
  onChangeFromInput($event) {
    const value = $event.target.value;
    let parseDate = value ? this.dateConverter.parse(value, this.dateFormat, this.locale) : null;
    if (parseDate) {
      if (parseDate.getTime() < this.minDate.getTime()) {
        parseDate = this.minDate;
      }

      if (parseDate.getTime() > this.maxDate.getTime()) {
        parseDate = this.maxDate;
      }
    }

    this.writeValue(parseDate);
    this.onChange(this.selectedDate);
  }

  @HostListener('keyup.esc', ['$event'])
  onEscKeyup() {
    this.hide();
  }

  ngOnDestroy(): void {
    this.removePopView();
  }

  private removePopView() {
    if (this.cmpRef) {
      this.cmpRef.destroy();
    }
  }

  private writeModelValue(selectDate: Date) {
    const value = selectDate ? this.dateConverter.format(selectDate, this.getDateFormat(), this.locale) : '';
    this.renderer.setProperty(this.elementRef.nativeElement, 'value', value);
    if (this.isOpen) {
      this.cmpRef.instance.writeValue(selectDate);
      this.onTouched();
    }
  }

  private getDateFormat() {
    if (this.dateFormat) {
      return this.dateFormat;
    }
    return this.showTimePicker ? this.dateConfig.format.time : this.dateConfig.format.date;
  }

  private applyPopupStyling(nativeElement: any) {
    this.renderer.addClass(nativeElement, 'dropdown-menu');
    this.renderer.setStyle(nativeElement, 'padding', '0px');
  }

  private fillPopupData() {
    ['showTimePicker', 'maxDate', 'minDate', 'cssClass', 'disabled', 'dateConverter', 'locale', 'dateFormat']
      .forEach(key => {
        if (this[key] !== undefined) {
          this.cmpRef.instance[key] = this[key];
        }
      });
  }
}

results matching ""

    No results matching ""