ronaldkwandy

Untitled

Sep 10th, 2020
1,183
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import { Component, ElementRef, Input, Output, EventEmitter, ViewEncapsulation, forwardRef, ViewChild, Injector } from '@angular/core';
  2. import { ControlValueAccessor, NG_VALUE_ACCESSOR, NgModel, NgControl, ValidationErrors } from '@angular/forms';
  3.  
  4. import { MomentDateAdapter } from '@angular/material-moment-adapter';
  5. import { MAT_DATE_LOCALE, DateAdapter, MAT_DATE_FORMATS, MatDatepicker } from '@angular/material';
  6.  
  7. import { ObjectHelper } from '../helper/object-helper';
  8. import { TranslateService } from '@ngx-translate/core';
  9.  
  10. import * as moment from 'moment';
  11.  
  12. export const YEARMONTHINPUT_CONTROL_VALUE_ACCESSOR: any = {
  13.   provide: NG_VALUE_ACCESSOR,
  14.   useExisting: forwardRef(() => YearMonthInputComponent),
  15.   multi: true
  16. };
  17.  
  18. export const MY_FORMATS = {
  19.   parse: {
  20.     dateInput: 'MM/YYYY',
  21.   },
  22.   display: {
  23.     dateInput: 'MM/YYYY',
  24.     monthYearLabel: 'MMM YYYY',
  25.     dateA11yLabel: 'LL',
  26.     monthYearA11yLabel: 'MMMM YYYY',
  27.   },
  28. };
  29.  
  30. @Component({
  31.   selector: 'app-year-month',
  32.   templateUrl: 'year-month-input.component.html',
  33.   encapsulation: ViewEncapsulation.None,
  34.   providers: [
  35.     YEARMONTHINPUT_CONTROL_VALUE_ACCESSOR,
  36.     { provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE] },
  37.     { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS }
  38.   ]
  39. })
  40. export class YearMonthInputComponent implements ControlValueAccessor {
  41.  
  42.   public static nextId = 0;
  43.  
  44.   @Output() public valueChange: EventEmitter<any>;
  45.   @ViewChild('yearMonthInput') public yearMonthInput: ElementRef;
  46.   @ViewChild('input') public input: NgModel;
  47.  
  48.   public mask: any[];
  49.   public value: Date;
  50.   public selectedValue: Date;
  51.   public errorState: boolean;
  52.   public errorMessage: string;
  53.   public styleClass: any;
  54.  
  55.   private _name: string;
  56.   private _errorKey: string;
  57.   private _placeholder: string;
  58.   private _required: boolean;
  59.   private _disabled: boolean;
  60.   private _focus: boolean;
  61.   private _message: string;
  62.   private _floatLabel: boolean;
  63.   private yearMonthRegex = new RegExp(/^(0?[1-9]|1[012])[\/\-]\d{4}$/);
  64.   private yearMonthRegexWithoutSpecialCharacter = new RegExp(/^(0?[1-9]|1[012])\d{4}$/);
  65.  
  66.   public propagateChange = (_: any) => { /* do nothing */ };
  67.   public propagateTouch = (_: any) => { /* do nothing */ };
  68.  
  69.   constructor(
  70.     private injector: Injector,
  71.     private translateService: TranslateService
  72.   ) {
  73.     this.valueChange = new EventEmitter<any>();
  74.  
  75.     this.name = `app-year-month-${YearMonthInputComponent.nextId++}`;
  76.     this.placeholder = null;
  77.     this.required = false;
  78.     this.floatLabel = true;
  79.     this.errorState = false;
  80.     this.errorMessage = null;
  81.     this.disabled = false;
  82.     this.mask = [];
  83.     this.styleClass = { width: 'auto' };
  84.   }
  85.  
  86.   public writeValue(value: any): void {
  87.     if (value === null || value === undefined || value === '') {
  88.       this.value = null;
  89.       this.selectedValue = null;
  90.     } else {
  91.       const strValue = (value + '').trim();
  92.       if (!isNaN(Number(value)) && strValue.length === 6) {
  93.         const dateValue = moment(strValue.substr(0, 4) + '-' + strValue.substr(4, 6) + '-01').toDate();
  94.         this.value = dateValue;
  95.         this.selectedValue = dateValue;
  96.       } else {
  97.         this.value = null;
  98.         this.selectedValue = null;
  99.       }
  100.     }
  101.   }
  102.  
  103.   public registerOnChange(fn: (_: any) => {}): void {
  104.     this.propagateChange = fn;
  105.   }
  106.  
  107.   public registerOnTouched(fn: (_: any) => {}): void {
  108.     this.propagateTouch = fn;
  109.   }
  110.  
  111.   public setDisabledState(isDisabled: boolean): void {
  112.     this.disabled = isDisabled;
  113.   }
  114.  
  115.   @Input()
  116.   public get name(): string { return this._name; }
  117.   public set name(name: string) { this._name = name; }
  118.  
  119.   @Input()
  120.   public get errorKey(): string { return this._errorKey; }
  121.   public set errorKey(errorKey: string) { this._errorKey = errorKey; }
  122.  
  123.   @Input()
  124.   public get placeholder(): string { return this._placeholder; }
  125.   public set placeholder(placeholder: string) { this._placeholder = placeholder; }
  126.  
  127.   @Input()
  128.   public get required(): boolean { return this._required; }
  129.   public set required(required: boolean) { this._required = required; }
  130.  
  131.   @Input()
  132.   public get focus(): boolean { return this._focus; }
  133.   public set focus(focus: boolean) {
  134.     this._focus = focus;
  135.     if (focus === true) {
  136.       this.yearMonthInput.nativeElement.focus();
  137.     }
  138.   }
  139.  
  140.   @Input()
  141.   public get message(): string { return this._message; }
  142.   public set message(message: string) { this._message = message; }
  143.  
  144.   @Input()
  145.   public get floatLabel(): boolean { return this._floatLabel; }
  146.   public set floatLabel(floatLabel: boolean) { this._floatLabel = floatLabel; }
  147.  
  148.   @Input()
  149.   public get disabled(): boolean { return this._disabled; }
  150.   public set disabled(disabled: boolean) { this._disabled = disabled; }
  151.  
  152.   public _onValueChange(value) {
  153.     if (value) {
  154.       if (value instanceof Date) {
  155.         if (moment(value).isValid()) {
  156.           this.value = moment(value).toDate();
  157.           this.propagateChange(moment(value).format('YYYYMM'));
  158.           this.valueChange.emit(moment(value).format('YYYYMM'));
  159.         } else {
  160.           this.value = null;
  161.           this.propagateChange(null);
  162.           this.valueChange.emit(null);
  163.         }
  164.       } else {
  165.         // format : MM/YYYY
  166.         const strYearMonth = String(value.creationData().input);
  167.         if (strYearMonth.length === 7) {
  168.           if (this.yearMonthRegex.test(strYearMonth)) {
  169.             this.errorState = false;
  170.             const formatedValue = strYearMonth.substr(3, 4) + '' + strYearMonth.substr(0, 2);
  171.  
  172.             // Note : new Date month start from 0 to 11
  173.             this.value = new Date(Number(strYearMonth.substr(3, 4)), Number(strYearMonth.substr(0, 2)) - 1, 1);
  174.             this.propagateChange(formatedValue);
  175.             this.valueChange.emit(formatedValue);
  176.           } else {
  177.             this.errorState = true;
  178.  
  179.             this.value = null;
  180.             this.propagateChange(null);
  181.             this.valueChange.emit(null);
  182.           }
  183.         } else if (strYearMonth.length === 6) {
  184.           if (this.yearMonthRegexWithoutSpecialCharacter.test(String(value.creationData().input))) {
  185.             this.errorState = false;
  186.             const formatedValue = strYearMonth.substr(2, 4) + '' + strYearMonth.substr(0, 2);
  187.  
  188.             // Note : new Date month start from 0 to 11
  189.             this.value = new Date(Number(strYearMonth.substr(3, 4)), Number(strYearMonth.substr(0, 2)) - 1, 1);
  190.             this.propagateChange(formatedValue);
  191.             this.valueChange.emit(formatedValue);
  192.           } else {
  193.             this.errorState = true;
  194.  
  195.             this.value = null;
  196.             this.propagateChange(null);
  197.             this.valueChange.emit(null);
  198.           }
  199.         } else {
  200.           this.errorState = true;
  201.  
  202.           this.value = null;
  203.           this.propagateChange(null);
  204.           this.valueChange.emit(null);
  205.         }
  206.       }
  207.       this.validate();
  208.     } else {
  209.       this.propagateChange(value);
  210.       this.valueChange.emit(value);
  211.       this.validate();
  212.     }
  213.   }
  214.  
  215.   public chosenYearHandler(normalizedYear: moment.Moment) {
  216.     this.value = moment(normalizedYear).toDate();
  217.     const ctrlValue = moment(this.value);
  218.     ctrlValue.year(normalizedYear.year());
  219.     this.value = moment(ctrlValue).toDate();
  220.   }
  221.  
  222.   public chosenMonthHandler(normlizedMonth: moment.Moment, datepicker: MatDatepicker<moment.Moment>) {
  223.     this.value = moment(normlizedMonth).toDate();
  224.     this.selectedValue = moment(normlizedMonth).toDate();
  225.     const ctrlValue = moment(this.value);
  226.     ctrlValue.month(normlizedMonth.month());
  227.  
  228.     this.propagateChange(moment(ctrlValue).format('YYYYMM'));
  229.     this.valueChange.emit(moment(ctrlValue).format('YYYYMM'));
  230.     this.value = moment(ctrlValue).toDate();
  231.     this.selectedValue = moment(ctrlValue).toDate();
  232.     this.input.control.setValue(moment(ctrlValue).toDate());
  233.     datepicker.close();
  234.  
  235.     this.validate();
  236.   }
  237.  
  238.   private validate() {
  239.     this.styleClass = { width: this.yearMonthInput.nativeElement.clientWidth ? 'calc(' + this.yearMonthInput.nativeElement.clientWidth + 'px)' : 'auto' };
  240.  
  241.     try {
  242.       const ngControl: NgControl | NgModel = this.injector.get(NgControl);
  243.       let errors: ValidationErrors = {};
  244.       if (ngControl instanceof NgModel) {
  245.         if (this.input.valid) {
  246.           this.errorState = false;
  247.         } else {
  248.           this.errorState = true;
  249.         }
  250.  
  251.         errors = this.input.errors;
  252.       } else {
  253.         if (ngControl.invalid) {
  254.           this.errorState = true;
  255.         } else {
  256.           this.errorState = false;
  257.         }
  258.  
  259.         errors = ngControl.errors;
  260.       }
  261.  
  262.       for (const key in errors) {
  263.         if (key) {
  264.           let keyMessage = null;
  265.           let params = null;
  266.           if (errors.matDatepickerParse) {
  267.             keyMessage = ObjectHelper.composeMessageKey(this.message, this.errorKey, 'pattern');
  268.             params = null;
  269.           } else {
  270.             keyMessage = ObjectHelper.composeMessageKey(this.message, this.errorKey, key);
  271.             params = ObjectHelper.composeMessageParams(this.message, key, errors);
  272.           }
  273.  
  274.           if (params) {
  275.             this.translateService.get(keyMessage, params).subscribe(
  276.               (result) => {
  277.                 this.errorMessage = result;
  278.               }
  279.             );
  280.           } else {
  281.             this.translateService.get(keyMessage).subscribe(
  282.               (result) => {
  283.                 this.errorMessage = result;
  284.               }
  285.             );
  286.           }
  287.           break;
  288.         }
  289.       }
  290.     } catch (exception) {
  291.       console.warn('[YearMonthInput] Forms / NgModel not defined!', exception);
  292.     }
  293.   }
  294.  
  295.   public markInputAsTouched() {
  296.     this.validate();
  297.   }
  298. }
  299.  
RAW Paste Data