xambey

Datepicker with custom ControlValueAccessor

Nov 30th, 2020
169
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. @Component({
  2.   selector: 'adm-datepicker',
  3.   templateUrl: './datepicker.component.html',
  4.   styleUrls: ['./datepicker.component.less'],
  5.   providers: [
  6.     {
  7.       provide: NG_VALUE_ACCESSOR,
  8.       useExisting: forwardRef(() => DatepickerComponent),
  9.       multi: true,
  10.     },
  11.   ],
  12.   // viewProviders: [
  13.   //   {
  14.   //     provide: ControlContainer,
  15.   //     useFactory: (container: ControlContainer) => container,
  16.   //     deps: [[ControlContainer, new Optional(), new Host(), new SkipSelf()]]
  17.   //   }
  18.   // ],
  19.   changeDetection: ChangeDetectionStrategy.OnPush
  20. })
  21. export class DatepickerComponent implements OnInit, OnDestroy, ControlValueAccessor {
  22.   onChange: (value: Date) => void;
  23.   onTouched: () => void;
  24.  
  25.   @Input() maskConfig: TextMaskConfig = {
  26.     mask: false
  27.   };
  28.   Icons = Icons;
  29.  
  30.   @ViewChild(BsDatepickerDirective, { static: true })
  31.   protected bsDatepickerDirective: BsDatepickerDirective;
  32.   /**
  33.    * Filter on paste from clipboard
  34.    */
  35.   @Input() inputFilter: InputFilter;
  36.   /**
  37.    * Placeholder
  38.    */
  39.   @Input() placeholder: string;
  40.   /**
  41.    * Size of input field
  42.    */
  43.   @Input() nzSize: NzSizeLDSType = 'default';
  44.   /**
  45.    * Disable input field
  46.    */
  47.   @Input() disabled: boolean;
  48.   /**
  49.    * Config object for datepicker
  50.    */
  51.   @Input() bsConfig: Partial<BsDatepickerConfig> = {
  52.     dateInputFormat: DateTimeFormat.DATE,
  53.   };
  54.   /**
  55.    * Placement of a datepicker. Accepts: "top", "bottom", "left", "right"
  56.    */
  57.   @Input() placement: 'top' | 'bottom' | 'left' | 'right' = 'bottom';
  58.   /**
  59.    * Specifies events that should trigger. Supports a space separated list of
  60.    * event names.
  61.    */
  62.   @Input() triggers: string = 'click';
  63.   /**
  64.    * Close datepicker on outside click
  65.    */
  66.   @Input() outsideClick: boolean = true;
  67.   /**
  68.    * A selector specifying the element the datepicker should be appended to.
  69.    */
  70.   @Input() container: string = 'body';
  71.   /**
  72.    * Close picker on click ESC button
  73.    */
  74.   @Input() outsideEsc: boolean = true;
  75.   /**
  76.    * Minimum date which is available for selection
  77.    */
  78.   @Input() minDate: Date;
  79.   /**
  80.    * Maximum date which is available for selection
  81.    */
  82.   @Input() maxDate: Date;
  83.   /**
  84.    * Minimum view mode : day, month, or year
  85.    */
  86.   @Input() minMode: BsDatepickerViewMode;
  87.   /**
  88.    * Disable Certain days in the week
  89.    */
  90.   @Input() daysDisabled: number[];
  91.   /**
  92.    * Disable specific dates
  93.    */
  94.   @Input() datesDisabled: Date[];
  95.   /**
  96.    * Enable specific dates
  97.    */
  98.   @Input() datesEnabled: Date[];
  99.   /**
  100.    * Date custom classes
  101.    */
  102.   @Input() dateCustomClasses: DatepickerDateCustomClasses[];
  103.   /**
  104.    * Emits an event when the datepicker is shown
  105.    */
  106.   @Output() onShown: EventEmitter<any> = new EventEmitter<any>();
  107.   /**
  108.    * Emits an event when the datepicker is hidden
  109.    */
  110.   @Output() onHidden: EventEmitter<any> = new EventEmitter<any>();
  111.   value: Date;
  112.   /**
  113.    *
  114.    */
  115.   set bsValue(value: Date) {
  116.     if(value !== this.value) {
  117.       this.value = this.normalizeValue(value);
  118.  
  119.       // if (isNaN(this.value.getTime())) {
  120.       //   this?.ngControl?.control?.setErrors({
  121.       //     invalid: 'Неверный формат даты'
  122.       //   });
  123.       // } else {
  124.       //   this?.ngControl?.control?.setErrors({ });
  125.       // }
  126.       //
  127.       // this?.ngControl?.control?.setValue?.(this.value);
  128.       // this?.ngControl?.control?.markAsTouched({ onlySelf: true });
  129.  
  130.       this.onChange?.(this.value);
  131.     }
  132.   }
  133.   get bsValue(): Date {
  134.     return this.value;
  135.   }
  136.   /**
  137.    * Picker's value
  138.    */
  139.   /**
  140.    * Returns whether or not the datepicker is currently being shown
  141.    */
  142.   get isOpen(): boolean {
  143.     return this?.bsDatepickerDirective?.isOpen;
  144.   }
  145.   /**
  146.    * Indicates whether datepicker's content is enabled or not
  147.    */
  148.   get isDisabled(): boolean {
  149.     return this?.bsDatepickerDirective?.isDisabled;
  150.   }
  151.   set isDisabled(value: boolean) {
  152.     this.bsDatepickerDirective.isDisabled = value;
  153.   }
  154.  
  155.   constructor(
  156.     protected bsLocaleService: BsLocaleService,
  157.     protected cdr: ChangeDetectorRef,
  158.     // @Optional() @Self() protected ngControl: NgControl,
  159.   ) {
  160.     // ngControl.valueAccessor = this;
  161.   }
  162.  
  163.   ngOnDestroy(): void {
  164.         throw new Error('Method not implemented.');
  165.     }
  166.  
  167.   ngOnInit() {
  168.     this.bsLocaleService.use('ru');
  169.  
  170.     // this?.ngControl?.control?.setValidators()
  171.     // this?.ngControl?.valueChanges?.pipe?.(
  172.     //   untilDestroyed(this)
  173.     // ).subscribe(value => this.writeValue(value));
  174.   }
  175.  
  176.   /**
  177.    * Opens an element’s datepicker. This is considered a “manual” triggering of the datepicker.
  178.    */
  179.   show() {
  180.     this?.bsDatepickerDirective?.show?.();
  181.     this.detectChanges();
  182.   }
  183.  
  184.   /**
  185.    * Closes an element’s datepicker. This is considered a “manual” triggering of the datepicker.
  186.    */
  187.   hide() {
  188.     this?.bsDatepickerDirective?.hide?.();
  189.     this.detectChanges();
  190.   }
  191.  
  192.   /**
  193.    * Toggles an element’s datepicker. This is considered a “manual” triggering of the datepicker.
  194.    */
  195.   toggle() {
  196.     this?.bsDatepickerDirective?.toggle?.();
  197.     this.detectChanges();
  198.   }
  199.  
  200.   detectChanges() {
  201.     this.cdr.markForCheck();
  202.   }
  203.  
  204.   registerOnChange(fn: any): void {
  205.     this.onChange = fn;
  206.   }
  207.  
  208.   registerOnTouched(fn: any): void {
  209.     this.onTouched = fn;
  210.   }
  211.  
  212.   setDisabledState(isDisabled: boolean): void {
  213.     this.disabled = isDisabled;
  214.     this.isDisabled = isDisabled;
  215.  
  216.     this.detectChanges();
  217.   }
  218.  
  219.   protected normalizeValue(value: Date) {
  220.     if (value) {
  221.       return typeof value === 'string' ? new Date(value) : value;
  222.     }
  223.  
  224.     return null;
  225.   }
  226.  
  227.   writeValue(value: Date): void {
  228.     if(value !== this.value) {
  229.       this.value = this.normalizeValue(value);
  230.       this.detectChanges();
  231.     }
  232.   }
  233.  
  234.   @HostListener('blur')
  235.   onBlur() {
  236.     this?.onTouched?.();
  237.     // this?.ngControl?.control?.markAsTouched({ onlySelf: true });
  238.   }
  239. }
  240.  
RAW Paste Data