@angular/forms#Validator TypeScript Examples

The following examples show how to use @angular/forms#Validator. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: ion-intl-tel-input.directive.ts    From ion-intl-tel-input with MIT License 6 votes vote down vote up
@Directive({
  // tslint:disable-next-line: directive-selector
  selector: '[ionIntlTelInputValid]',
  providers: [
    {
      provide: NG_VALIDATORS,
      useExisting: IonIntlTelInputValidatorDirective,
      multi: true,
    },
  ],
})
export class IonIntlTelInputValidatorDirective implements Validator {
  validate(control: AbstractControl): ValidationErrors | null {
    return IonIntlTelInputValidators.phone(control);
  }
}
Example #2
Source File: forbitten-email-validator.directive.ts    From mns with MIT License 6 votes vote down vote up
// REF: https://angular.io/guide/form-validation#defining-custom-validators
// TODO@Idrice
// 1. Defining custom validators i.e Email.


@Directive({
  selector: '[appForbittenEmail]',
  providers: [{ provide: NG_VALIDATORS, useExisting: ForbittenEmailValidatorDirective, multi: true }]
})
export class ForbittenEmailValidatorDirective implements Validator {

  // Defintion of Storage HTML property named appForbiddenEmail in forbiddenEmail
  @Input('appForbittenEmail') forbittenEmail!: string;

  constructor() { }

  // Return typ ?
  // Control ie. input element
  validate(control: AbstractControl): { [key: string]: any } | null {
    console.log('Directive--> ' + control.errors);
    // Nice.. see how to  define RegExp object in angular

    // Execute validation logic --> ValidationErrors
    const response = this.forbittenEmail ? forbittenEmailValidator()(control) : null;
    // const l = JSON.stringify(response);
    // console.log(' Response= ' + l + ' ' + response.forbiddenEmail);
    return response;
  }


}
Example #3
Source File: forbitten-fName-validator.directive.ts    From mns with MIT License 6 votes vote down vote up
// REF: https://angular.io/guide/form-validation#defining-custom-validators


@Directive({
  selector: '[appForbittenFname]',
  providers: [{ provide: NG_VALIDATORS, useExisting: ForbittenFnameValidatorDirective, multi: true }]
})
export class ForbittenFnameValidatorDirective implements Validator {

  // Defintion of Storage HTML property named appForbiddenFname in forbiddenFname
  @Input('appForbittenFname') forbittenFname: string;

  constructor() { }

  // Return typ ?
  // Control ie. input element
  validate(control: AbstractControl): { [key: string]: any } | null {
    console.log('Directive--> ' + control.errors);
    // Nice.. see how to  define RegExp object in angular

    // Execute validation logic --> ValidationErrors
    const response = this.forbittenFname ? forbittenFnameValidator()(control) : null;
    // const l = JSON.stringify(response);
    // console.log(' Response= ' + l + ' ' + response.forbiddenFname);
    return response;
  }


}
Example #4
Source File: forbitten-password-validator.directive.ts    From mns with MIT License 6 votes vote down vote up
@Directive({
  selector: '[appForbittenPassword]',
  providers: [{ provide: NG_VALIDATORS, useExisting: ForbittenPasswordValidatorDirective, multi: true }]
})
export class ForbittenPasswordValidatorDirective implements Validator {

  // Defintion of Storage HTML property named appForbiddenPassword in forbiddenPassword
  @Input('appForbittenPassword') forbittenPassword!: string;

  constructor() { }

  // Return typ ?
  // Control ie. input element
  validate(control: AbstractControl): { [key: string]: any } | null {
    console.log('Directive--> ' + control.errors);
    // Nice.. see how to  define RegExp object in angular

    // Execute validation logic --> ValidationErrors
    const response = this.forbittenPassword ? forbittenPasswordValidator()(control) : null;
    // const l = JSON.stringify(response);
    // console.log(' Response= ' + l + ' ' + response.forbiddenPassword);
    return response;
  }


}
Example #5
Source File: validators.ts    From alauda-ui with MIT License 5 votes vote down vote up
@Directive({
  selector:
    // eslint-disable-next-line @angular-eslint/directive-selector
    'aui-select[ngModel][includes],aui-select[formControl][includes],aui-select[formControlName][includes]',
  providers: [
    {
      provide: NG_VALIDATORS,
      useExisting: forwardRef(() => IncludesDirective),
      multi: true,
    },
  ],
})
export class IncludesDirective<T> implements Validator, AfterContentInit {
  @Input()
  get includes() {
    return this._includes;
  }

  set includes(val: boolean | '') {
    this._includes = coerceAttrBoolean(val);
    if (this.onValidatorChange) {
      this.onValidatorChange();
    }
  }

  @Input()
  trackFn: TrackFn<T>;

  private _includes = false;

  onValidatorChange: () => void;

  constructor(private readonly selectRef: SelectComponent<T>) {}

  ngAfterContentInit() {
    this.selectRef.contentOptions.changes.subscribe(() => {
      if (this.onValidatorChange) {
        this.onValidatorChange();
      }
    });
  }

  registerOnValidatorChange(fn: () => void) {
    this.onValidatorChange = fn;
  }

  validate(control: AbstractControl): ValidationErrors {
    if (!this.selectRef.contentOptions || !control.value) {
      return;
    }
    return !this.includes
      ? null
      : AuiSelectValidators.includes(
          this.selectRef.contentOptions
            .filter(option => !option.disabled)
            .map(option => option.value),
          this.trackFn,
        )(control);
  }
}
Example #6
Source File: color-input.component.ts    From angular-material-components with MIT License 4 votes vote down vote up
@Directive({
  selector: 'input[ngxMatColorPicker]',
  providers: [
    MAT_COLORPICKER_VALUE_ACCESSOR,
    MAT_COLORPICKER_VALIDATORS,
    { provide: MAT_INPUT_VALUE_ACCESSOR, useExisting: NgxMatColorPickerInput },
  ],
  host: {
    '[attr.aria-haspopup]': '_picker ? "dialog" : null',
    '[attr.aria-owns]': '(_picker?.opened && _picker.id) || null',
    '[disabled]': 'disabled',
    '(input)': '_onInput($event.target.value)',
    '(change)': '_onChange()',
    '(blur)': '_onBlur()',
    '(keydown)': '_onKeydown($event)',
  },
  exportAs: 'ngxMatColorPickerInput',
})
export class NgxMatColorPickerInput implements ControlValueAccessor, OnInit, OnDestroy, Validator {

  @Input()
  set ngxMatColorPicker(value: NgxMatColorPickerComponent) {
    if (!value) {
      return;
    }

    this._picker = value;
    this._picker.registerInput(this);
    this._pickerSubscription.unsubscribe();

    this._pickerSubscription = this._picker._selectedChanged.subscribe((selected: Color) => {
      this.value = selected;
      this._cvaOnChange(selected);
      this._onTouched();
      this.colorInput.emit(new NgxMatColorPickerInputEvent(this, this._elementRef.nativeElement));
      this.colorChange.emit(new NgxMatColorPickerInputEvent(this, this._elementRef.nativeElement));
    });
  }
  _picker: NgxMatColorPickerComponent;

  /** Whether the colorpicker-input is disabled. */
  @Input()
  get disabled(): boolean { return !!this._disabled; }
  set disabled(value: boolean) {
    const newValue = coerceBooleanProperty(value);
    const element = this._elementRef.nativeElement;

    if (this._disabled !== newValue) {
      this._disabled = newValue;
      this._disabledChange.emit(newValue);
    }

    // We need to null check the `blur` method, because it's undefined during SSR.
    if (newValue && element.blur) {
      // Normally, native input elements automatically blur if they turn disabled. This behavior
      // is problematic, because it would mean that it triggers another change detection cycle,
      // which then causes a changed after checked error if the input element was focused before.
      element.blur();
    }
  }
  private _disabled: boolean;

  /** The value of the input. */
  @Input()
  get value(): Color | null { return this._value; }
  set value(value: Color | null) {
    const oldValue = this.value;
    this._value = value;
    this._formatValue(value);

    if (!this._adapter.sameColor(oldValue, value)) {
      this._valueChange.emit(value);
    }

  }
  private _value: Color | null;

  /** Emits when a `change` event is fired on this `<input>`. */
  @Output() readonly colorChange: EventEmitter<NgxMatColorPickerInputEvent> =
    new EventEmitter<NgxMatColorPickerInputEvent>();

  /** Emits when an `input` event is fired on this `<input>`. */
  @Output() readonly colorInput: EventEmitter<NgxMatColorPickerInputEvent> =
    new EventEmitter<NgxMatColorPickerInputEvent>();

  /** Emits when the disabled state has changed */
  _disabledChange = new EventEmitter<boolean>();

  /** Emits when the value changes (either due to user input or programmatic change). */
  _valueChange = new EventEmitter<Color>();

  _onTouched = () => { };

  private _cvaOnChange: (value: any) => void = () => { };

  private _validatorOnChange = () => { };

  private _pickerSubscription = Subscription.EMPTY;

  /** The combined form control validator for this input. */
  private _validator: ValidatorFn | null =
    Validators.compose([]);

  /** Whether the last value set on the input was valid. */
  private _lastValueValid = false;

  constructor(private _elementRef: ElementRef<HTMLInputElement>,
    @Optional() private _formField: MatFormField,
    @Optional() @Inject(MAT_COLOR_FORMATS) private _colorFormats: MatColorFormats,
    private _adapter: ColorAdapter) {
    if (!this._colorFormats) {
      throw createMissingDateImplError('MAT_COLOR_FORMATS');
    }
  }

  /** Returns the palette used by the input's form field, if any. */
  public getThemePalette(): ThemePalette {
    return this._formField ? this._formField.color : undefined;
  }


  registerOnValidatorChange(fn: () => void): void {
    this._validatorOnChange = fn;
  }


  validate(c: AbstractControl): ValidationErrors | null {
    return this._validator ? this._validator(c) : null;
  }

  /**
   * @deprecated
   * @breaking-change 8.0.0 Use `getConnectedOverlayOrigin` instead
   */
  getPopupConnectionElementRef(): ElementRef {
    return this.getConnectedOverlayOrigin();
  }

  /**
  * Gets the element that the colorpicker popup should be connected to.
  * @return The element to connect the popup to.
  */
  getConnectedOverlayOrigin(): ElementRef {
    return this._formField ? this._formField.getConnectedOverlayOrigin() : this._elementRef;
  }


  ngOnInit() {
  }

  ngOnDestroy(): void {
    this._pickerSubscription.unsubscribe();
    this._valueChange.complete();
    this._disabledChange.complete();
  }

  // Implemented as part of ControlValueAccessor.
  writeValue(value: Color): void {
    this.value = value;
  }

  // Implemented as part of ControlValueAccessor.
  registerOnChange(fn: (value: any) => void): void {
    this._cvaOnChange = fn;
  }

  // Implemented as part of ControlValueAccessor.
  registerOnTouched(fn: () => void): void {
    this._onTouched = fn;
  }

  // Implemented as part of ControlValueAccessor.
  setDisabledState(isDisabled: boolean): void {
    this.disabled = isDisabled;
  }

  _onChange() {
    this.colorChange.emit(new NgxMatColorPickerInputEvent(this, this._elementRef.nativeElement));
  }

  _onKeydown(event: KeyboardEvent) {
    const isAltDownArrow = event.altKey && event.keyCode === DOWN_ARROW;

    if (this._picker && isAltDownArrow && !this._elementRef.nativeElement.readOnly) {
      this._picker.open();
      event.preventDefault();
    }
  }

  /** Handles blur events on the input. */
  _onBlur() {
    // Reformat the input only if we have a valid value.
    if (this.value) {
      this._formatValue(this.value);
    }

    this._onTouched();
  }

  /** Formats a value and sets it on the input element. */
  private _formatValue(value: Color | null) {
    this._elementRef.nativeElement.value = value ? this._adapter.format(value, this._colorFormats.display.colorInput) : '';
  }

  _onInput(value: string) {
    const lastValueWasValid = this._lastValueValid;
    const nextValue = this._adapter.parse(value);

    if (!this._adapter.sameColor(nextValue, this._value)) {
      this._value = nextValue;
      this._cvaOnChange(nextValue);
      this._valueChange.emit(nextValue);
      this.colorInput.emit(new NgxMatColorPickerInputEvent(this, this._elementRef.nativeElement));
    } else if (lastValueWasValid !== this._lastValueValid) {
      this._validatorOnChange();
    }
  }

}
Example #7
Source File: datetime-input.ts    From angular-material-components with MIT License 4 votes vote down vote up
/** Directive used to connect an input to a matDatetimePicker. */
@Directive({
    selector: 'input[ngxMatDatetimePicker]',
    providers: [
        MAT_DATEPICKER_VALUE_ACCESSOR,
        MAT_DATEPICKER_VALIDATORS,
        { provide: MAT_INPUT_VALUE_ACCESSOR, useExisting: NgxMatDatetimeInput },
    ],
    host: {
        '[attr.aria-haspopup]': '_datepicker ? "dialog" : null',
        '[attr.aria-owns]': '(_datepicker?.opened && _datepicker.id) || null',
        '[attr.min]': 'min ? _dateAdapter.toIso8601(min) : null',
        '[attr.max]': 'max ? _dateAdapter.toIso8601(max) : null',
        '[disabled]': 'disabled',
        '(input)': '_onInput($event.target.value)',
        '(change)': '_onChange()',
        '(blur)': '_onBlur()',
        '(focus)': '_onFocus()',
        '(keydown)': '_onKeydown($event)',
    },
    exportAs: 'ngxMatDatetimePickerInput',
})
export class NgxMatDatetimeInput<D> implements ControlValueAccessor, OnDestroy, Validator {
    /** The datepicker that this input is associated with. */
    @Input()
    set ngxMatDatetimePicker(value: NgxMatDatetimePicker<D>) {
        if (!value) {
            return;
        }

        this._datepicker = value;
        this._datepicker._registerInput(this);
        this._datepickerSubscription.unsubscribe();

        this._datepickerSubscription = this._datepicker._selectedChanged.subscribe((selected: D) => {
            this.value = selected;
            this._cvaOnChange(selected);
            this._onTouched();
            this.dateInput.emit(new MatDatetimePickerInputEvent(this, this._elementRef.nativeElement));
            this.dateChange.emit(new MatDatetimePickerInputEvent(this, this._elementRef.nativeElement));
        });
    }
    _datepicker: NgxMatDatetimePicker<D>;

    /** Function that can be used to filter out dates within the datepicker. */
    @Input()
    set ngxMatDatetimePickerFilter(value: (date: D | null) => boolean) {
        this._dateFilter = value;
        this._validatorOnChange();
    }
    _dateFilter: (date: D | null) => boolean;

    /** The value of the input. */
    @Input()
    get value(): D | null { return this._value; }
    set value(value: D | null) {
        value = this._dateAdapter.deserialize(value);
        this._lastValueValid = !value || this._dateAdapter.isValid(value);
        value = this._getValidDateOrNull(value);
        const oldDate = this.value;
        this._value = value;
        this._formatValue(value);

        if (!this._dateAdapter.sameDate(oldDate, value)) {
            this._valueChange.emit(value);
        }
    }
    private _value: D | null;

    /** The minimum valid date. */
    @Input()
    get min(): D | null { return this._min; }
    set min(value: D | null) {
        this._min = this._getValidDateOrNull(this._dateAdapter.deserialize(value));
        this._validatorOnChange();
    }
    private _min: D | null;

    /** The maximum valid date. */
    @Input()
    get max(): D | null { return this._max; }
    set max(value: D | null) {
        this._max = this._getValidDateOrNull(this._dateAdapter.deserialize(value));
        this._validatorOnChange();
    }
    private _max: D | null;

    /** Whether the datepicker-input is disabled. */
    @Input()
    get disabled(): boolean { return !!this._disabled; }
    set disabled(value: boolean) {
        const newValue = value != null && `${value}` !== 'false';
        const element = this._elementRef.nativeElement;

        if (this._disabled !== newValue) {
            this._disabled = newValue;
            this._disabledChange.emit(newValue);
        }

        // We need to null check the `blur` method, because it's undefined during SSR.
        if (newValue && element.blur) {
            // Normally, native input elements automatically blur if they turn disabled. This behavior
            // is problematic, because it would mean that it triggers another change detection cycle,
            // which then causes a changed after checked error if the input element was focused before.
            element.blur();
        }
    }
    private _disabled: boolean;

    /** Emits when a `change` event is fired on this `<input>`. */
    @Output() readonly dateChange: EventEmitter<MatDatetimePickerInputEvent<D>> =
        new EventEmitter<MatDatetimePickerInputEvent<D>>();

    /** Emits when an `input` event is fired on this `<input>`. */
    @Output() readonly dateInput: EventEmitter<MatDatetimePickerInputEvent<D>> =
        new EventEmitter<MatDatetimePickerInputEvent<D>>();

    /** Emits when the value changes (either due to user input or programmatic change). */
    _valueChange = new EventEmitter<D | null>();

    /** Emits when the disabled state has changed */
    _disabledChange = new EventEmitter<boolean>();

    _onTouched = () => { };

    private _cvaOnChange: (value: any) => void = () => { };

    private _validatorOnChange = () => { };

    private _datepickerSubscription = Subscription.EMPTY;

    private _localeSubscription = Subscription.EMPTY;

    /** The form control validator for whether the input parses. */
    private _parseValidator: ValidatorFn = (): ValidationErrors | null => {
        return this._lastValueValid ?
            null : { 'matDatetimePickerParse': { 'text': this._elementRef.nativeElement.value } };
    }

    /** The form control validator for the min date. */
    private _minValidator: ValidatorFn = (control: AbstractControl): ValidationErrors | null => {
        const controlValue = this._getValidDateOrNull(this._dateAdapter.deserialize(control.value));
        return (!this.min || !controlValue ||
            this._dateAdapter.compareDateWithTime(this.min, controlValue, this._datepicker.showSeconds) <= 0) ?
            null : { 'matDatetimePickerMin': { 'min': this.min, 'actual': controlValue } };
    }

    /** The form control validator for the max date. */
    private _maxValidator: ValidatorFn = (control: AbstractControl): ValidationErrors | null => {
        const controlValue = this._getValidDateOrNull(this._dateAdapter.deserialize(control.value));
        return (!this.max || !controlValue ||
            this._dateAdapter.compareDateWithTime(this.max, controlValue, this._datepicker.showSeconds) >= 0) ?
            null : { 'matDatetimePickerMax': { 'max': this.max, 'actual': controlValue } };
    }

    /** The form control validator for the date filter. */
    private _filterValidator: ValidatorFn = (control: AbstractControl): ValidationErrors | null => {
        const controlValue = this._getValidDateOrNull(this._dateAdapter.deserialize(control.value));
        return !this._dateFilter || !controlValue || this._dateFilter(controlValue) ?
            null : { 'matDatetimePickerFilter': true };
    }

    /** The combined form control validator for this input. */
    private _validator: ValidatorFn | null =
        Validators.compose(
            [this._parseValidator, this._minValidator, this._maxValidator, this._filterValidator]);

    /** Whether the last value set on the input was valid. */
    private _lastValueValid = false;

    constructor(
        private _elementRef: ElementRef<HTMLInputElement>,
        @Optional() public _dateAdapter: NgxMatDateAdapter<D>,
        @Optional() @Inject(NGX_MAT_DATE_FORMATS) private _dateFormats: NgxMatDateFormats,
        @Optional() private _formField: MatFormField) {
        if (!this._dateAdapter) {
            throw createMissingDateImplError('NgxMatDateAdapter');
        }
        if (!this._dateFormats) {
            throw createMissingDateImplError('NGX_MAT_DATE_FORMATS');
        }

        // Update the displayed date when the locale changes.
        this._localeSubscription = _dateAdapter.localeChanges.subscribe(() => {
            this.value = this.value;
        });
    }

    ngOnDestroy() {
        this._datepickerSubscription.unsubscribe();
        this._localeSubscription.unsubscribe();
        this._valueChange.complete();
        this._disabledChange.complete();
    }

    /** @docs-private */
    registerOnValidatorChange(fn: () => void): void {
        this._validatorOnChange = fn;
    }

    /** @docs-private */
    validate(c: AbstractControl): ValidationErrors | null {
        return this._validator ? this._validator(c) : null;
    }

    /**
     * @deprecated
     * @breaking-change 8.0.0 Use `getConnectedOverlayOrigin` instead
     */
    getPopupConnectionElementRef(): ElementRef {
        return this.getConnectedOverlayOrigin();
    }

    /**
     * Gets the element that the datepicker popup should be connected to.
     * @return The element to connect the popup to.
     */
    getConnectedOverlayOrigin(): ElementRef {
        return this._formField ? this._formField.getConnectedOverlayOrigin() : this._elementRef;
    }

    // Implemented as part of ControlValueAccessor.
    writeValue(value: D): void {
        this.value = value;
    }

    // Implemented as part of ControlValueAccessor.
    registerOnChange(fn: (value: any) => void): void {
        this._cvaOnChange = fn;
    }

    // Implemented as part of ControlValueAccessor.
    registerOnTouched(fn: () => void): void {
        this._onTouched = fn;
    }

    // Implemented as part of ControlValueAccessor.
    setDisabledState(isDisabled: boolean): void {
        this.disabled = isDisabled;
    }

    _onKeydown(event: KeyboardEvent) {
        const isAltDownArrow = event.altKey && event.keyCode === DOWN_ARROW;

        if (this._datepicker && isAltDownArrow && !this._elementRef.nativeElement.readOnly) {
            this._datepicker.open();
            event.preventDefault();
        }
    }

    _onInput(value: string) {
        const lastValueWasValid = this._lastValueValid;
        let date = this._dateAdapter.parse(value, this._dateFormats.parse.dateInput);
        this._lastValueValid = !date || this._dateAdapter.isValid(date);
        date = this._getValidDateOrNull(date);

        const isSameTime = this._dateAdapter.isSameTime(date, this._value);

        if ((date != null && (!isSameTime || !this._dateAdapter.sameDate(date, this._value)))
            || (date == null && this._value != null)) {
            this._value = date;
            this._cvaOnChange(date);
            this._valueChange.emit(date);
            this.dateInput.emit(new MatDatetimePickerInputEvent(this, this._elementRef.nativeElement));
        } else if (lastValueWasValid !== this._lastValueValid) {
            this._validatorOnChange();
        }
    }

    _onChange() {
        this.dateChange.emit(new MatDatetimePickerInputEvent(this, this._elementRef.nativeElement));
    }

    /** Returns the palette used by the input's form field, if any. */
    _getThemePalette(): ThemePalette {
        return this._formField ? this._formField.color : undefined;
    }

    /** Handles blur events on the input. */
    _onBlur() {
        // Reformat the input only if we have a valid value.
        if (this.value) {
            this._formatValue(this.value);
        }

        this._onTouched();
    }

    /** Handles focus events on the input. */
    _onFocus() {
        // Close datetime picker if opened
        if (this._datepicker && this._datepicker.opened) {
            this._datepicker.cancel();
        }
    }

    /** Formats a value and sets it on the input element. */
    private _formatValue(value: D | null) {
        this._elementRef.nativeElement.value =
            value ? this._dateAdapter.format(value, this._dateFormats.display.dateInput) : '';
    }

    /**
     * @param obj The object to check.
     * @returns The given object if it is both a date instance and valid, otherwise null.
     */
    private _getValidDateOrNull(obj: any): D | null {
        return (this._dateAdapter.isDateInstance(obj) && this._dateAdapter.isValid(obj)) ? obj : null;
    }

}
Example #8
Source File: datetime-input.ts    From ngx-mat-datetime-picker with MIT License 4 votes vote down vote up
/** Directive used to connect an input to a matDatetimePicker. */
@Directive({
    selector: 'input[ngxMatDatetimePicker]',
    providers: [
        MAT_DATEPICKER_VALUE_ACCESSOR,
        MAT_DATEPICKER_VALIDATORS,
        { provide: MAT_INPUT_VALUE_ACCESSOR, useExisting: NgxMatDatetimeInput },
    ],
    host: {
        '[attr.aria-haspopup]': '_datepicker ? "dialog" : null',
        '[attr.aria-owns]': '(_datepicker?.opened && _datepicker.id) || null',
        '[attr.min]': 'min ? _dateAdapter.toIso8601(min) : null',
        '[attr.max]': 'max ? _dateAdapter.toIso8601(max) : null',
        '[disabled]': 'disabled',
        '(input)': '_onInput($event.target.value)',
        '(change)': '_onChange()',
        '(blur)': '_onBlur()',
        '(focus)': '_onFocus()',
        '(keydown)': '_onKeydown($event)',
    },
    exportAs: 'ngxMatDatetimePickerInput',
})
export class NgxMatDatetimeInput<D> implements ControlValueAccessor, OnDestroy, Validator {
    /** The datepicker that this input is associated with. */
    @Input()
    set ngxMatDatetimePicker(value: NgxMatDatetimePicker<D>) {
        if (!value) {
            return;
        }

        this._datepicker = value;
        this._datepicker._registerInput(this);
        this._datepickerSubscription.unsubscribe();

        this._datepickerSubscription = this._datepicker._selectedChanged.subscribe((selected: D) => {
            this.value = selected;
            this._cvaOnChange(selected);
            this._onTouched();
            this.dateInput.emit(new MatDatetimePickerInputEvent(this, this._elementRef.nativeElement));
            this.dateChange.emit(new MatDatetimePickerInputEvent(this, this._elementRef.nativeElement));
        });
    }
    _datepicker: NgxMatDatetimePicker<D>;

    /** Function that can be used to filter out dates within the datepicker. */
    @Input()
    set ngxMatDatetimePickerFilter(value: (date: D | null) => boolean) {
        this._dateFilter = value;
        this._validatorOnChange();
    }
    _dateFilter: (date: D | null) => boolean;

    /** The value of the input. */
    @Input()
    get value(): D | null { return this._value; }
    set value(value: D | null) {
        value = this._dateAdapter.deserialize(value);
        this._lastValueValid = !value || this._dateAdapter.isValid(value);
        value = this._getValidDateOrNull(value);
        const oldDate = this.value;
        this._value = value;
        this._formatValue(value);

        if (!this._dateAdapter.sameDate(oldDate, value)) {
            this._valueChange.emit(value);
        }
    }
    private _value: D | null;

    /** The minimum valid date. */
    @Input()
    get min(): D | null { return this._min; }
    set min(value: D | null) {
        this._min = this._getValidDateOrNull(this._dateAdapter.deserialize(value));
        this._validatorOnChange();
    }
    private _min: D | null;

    /** The maximum valid date. */
    @Input()
    get max(): D | null { return this._max; }
    set max(value: D | null) {
        this._max = this._getValidDateOrNull(this._dateAdapter.deserialize(value));
        this._validatorOnChange();
    }
    private _max: D | null;

    /** Whether the datepicker-input is disabled. */
    @Input()
    get disabled(): boolean { return !!this._disabled; }
    set disabled(value: boolean) {
        const newValue = value != null && `${value}` !== 'false';
        const element = this._elementRef.nativeElement;

        if (this._disabled !== newValue) {
            this._disabled = newValue;
            this._disabledChange.emit(newValue);
        }

        // We need to null check the `blur` method, because it's undefined during SSR.
        if (newValue && element.blur) {
            // Normally, native input elements automatically blur if they turn disabled. This behavior
            // is problematic, because it would mean that it triggers another change detection cycle,
            // which then causes a changed after checked error if the input element was focused before.
            element.blur();
        }
    }
    private _disabled: boolean;

    /** Emits when a `change` event is fired on this `<input>`. */
    @Output() readonly dateChange: EventEmitter<MatDatetimePickerInputEvent<D>> =
        new EventEmitter<MatDatetimePickerInputEvent<D>>();

    /** Emits when an `input` event is fired on this `<input>`. */
    @Output() readonly dateInput: EventEmitter<MatDatetimePickerInputEvent<D>> =
        new EventEmitter<MatDatetimePickerInputEvent<D>>();

    /** Emits when the value changes (either due to user input or programmatic change). */
    _valueChange = new EventEmitter<D | null>();

    /** Emits when the disabled state has changed */
    _disabledChange = new EventEmitter<boolean>();

    _onTouched = () => { };

    private _cvaOnChange: (value: any) => void = () => { };

    private _validatorOnChange = () => { };

    private _datepickerSubscription = Subscription.EMPTY;

    private _localeSubscription = Subscription.EMPTY;

    /** The form control validator for whether the input parses. */
    private _parseValidator: ValidatorFn = (): ValidationErrors | null => {
        return this._lastValueValid ?
            null : { 'matDatetimePickerParse': { 'text': this._elementRef.nativeElement.value } };
    }

    /** The form control validator for the min date. */
    private _minValidator: ValidatorFn = (control: AbstractControl): ValidationErrors | null => {
        const controlValue = this._getValidDateOrNull(this._dateAdapter.deserialize(control.value));
        return (!this.min || !controlValue ||
            this._dateAdapter.compareDateWithTime(this.min, controlValue, this._datepicker.showSeconds) <= 0) ?
            null : { 'matDatetimePickerMin': { 'min': this.min, 'actual': controlValue } };
    }

    /** The form control validator for the max date. */
    private _maxValidator: ValidatorFn = (control: AbstractControl): ValidationErrors | null => {
        const controlValue = this._getValidDateOrNull(this._dateAdapter.deserialize(control.value));
        return (!this.max || !controlValue ||
            this._dateAdapter.compareDateWithTime(this.max, controlValue,  this._datepicker.showSeconds) >= 0) ?
            null : { 'matDatetimePickerMax': { 'max': this.max, 'actual': controlValue } };
    }

    /** The form control validator for the date filter. */
    private _filterValidator: ValidatorFn = (control: AbstractControl): ValidationErrors | null => {
        const controlValue = this._getValidDateOrNull(this._dateAdapter.deserialize(control.value));
        return !this._dateFilter || !controlValue || this._dateFilter(controlValue) ?
            null : { 'matDatetimePickerFilter': true };
    }

    /** The combined form control validator for this input. */
    private _validator: ValidatorFn | null =
        Validators.compose(
            [this._parseValidator, this._minValidator, this._maxValidator, this._filterValidator]);

    /** Whether the last value set on the input was valid. */
    private _lastValueValid = false;

    constructor(
        private _elementRef: ElementRef<HTMLInputElement>,
        @Optional() public _dateAdapter: NgxMatDateAdapter<D>,
        @Optional() @Inject(MAT_DATE_FORMATS) private _dateFormats: MatDateFormats,
        @Optional() private _formField: MatFormField) {
        if (!this._dateAdapter) {
            throw createMissingDateImplError('NgxMatDateAdapter');
        }
        if (!this._dateFormats) {
            throw createMissingDateImplError('MAT_DATE_FORMATS');
        }

        // Update the displayed date when the locale changes.
        this._localeSubscription = _dateAdapter.localeChanges.subscribe(() => {
            this.value = this.value;
        });
    }

    ngOnDestroy() {
        this._datepickerSubscription.unsubscribe();
        this._localeSubscription.unsubscribe();
        this._valueChange.complete();
        this._disabledChange.complete();
    }

    /** @docs-private */
    registerOnValidatorChange(fn: () => void): void {
        this._validatorOnChange = fn;
    }

    /** @docs-private */
    validate(c: AbstractControl): ValidationErrors | null {
        return this._validator ? this._validator(c) : null;
    }

    /**
     * @deprecated
     * @breaking-change 8.0.0 Use `getConnectedOverlayOrigin` instead
     */
    getPopupConnectionElementRef(): ElementRef {
        return this.getConnectedOverlayOrigin();
    }

    /**
     * Gets the element that the datepicker popup should be connected to.
     * @return The element to connect the popup to.
     */
    getConnectedOverlayOrigin(): ElementRef {
        return this._formField ? this._formField.getConnectedOverlayOrigin() : this._elementRef;
    }

    // Implemented as part of ControlValueAccessor.
    writeValue(value: D): void {
        this.value = value;
    }

    // Implemented as part of ControlValueAccessor.
    registerOnChange(fn: (value: any) => void): void {
        this._cvaOnChange = fn;
    }

    // Implemented as part of ControlValueAccessor.
    registerOnTouched(fn: () => void): void {
        this._onTouched = fn;
    }

    // Implemented as part of ControlValueAccessor.
    setDisabledState(isDisabled: boolean): void {
        this.disabled = isDisabled;
    }

    _onKeydown(event: KeyboardEvent) {
        const isAltDownArrow = event.altKey && event.keyCode === DOWN_ARROW;

        if (this._datepicker && isAltDownArrow && !this._elementRef.nativeElement.readOnly) {
            this._datepicker.open();
            event.preventDefault();
        }
    }

    _onInput(value: string) {
        const lastValueWasValid = this._lastValueValid;
        let date = this._dateAdapter.parse(value, this._dateFormats.parse.dateInput);
        this._lastValueValid = !date || this._dateAdapter.isValid(date);
        date = this._getValidDateOrNull(date);

        const isSameTime = this._dateAdapter.isSameTime(date, this._value);

        if ((date != null && (!isSameTime || !this._dateAdapter.sameDate(date, this._value)))
            || (date == null && this._value != null)) {
            this._value = date;
            this._cvaOnChange(date);
            this._valueChange.emit(date);
            this.dateInput.emit(new MatDatetimePickerInputEvent(this, this._elementRef.nativeElement));
        } else if (lastValueWasValid !== this._lastValueValid) {
            this._validatorOnChange();
        }
    }

    _onChange() {
        this.dateChange.emit(new MatDatetimePickerInputEvent(this, this._elementRef.nativeElement));
    }

    /** Returns the palette used by the input's form field, if any. */
    _getThemePalette(): ThemePalette {
        return this._formField ? this._formField.color : undefined;
    }

    /** Handles blur events on the input. */
    _onBlur() {
        // Reformat the input only if we have a valid value.
        if (this.value) {
            this._formatValue(this.value);
        }

        this._onTouched();
    }

    /** Handles focus events on the input. */
    _onFocus() {
        // Close datetime picker if opened
        if(this._datepicker && this._datepicker.opened){
            this._datepicker.cancel();
        }
    }

    /** Formats a value and sets it on the input element. */
    private _formatValue(value: D | null) {
        this._elementRef.nativeElement.value =
            value ? this._dateAdapter.format(value, this._dateFormats.display.dateInput) : '';
    }

    /**
     * @param obj The object to check.
     * @returns The given object if it is both a date instance and valid, otherwise null.
     */
    private _getValidDateOrNull(obj: any): D | null {
        return (this._dateAdapter.isDateInstance(obj) && this._dateAdapter.isValid(obj)) ? obj : null;
    }

}
Example #9
Source File: np-file-upload.component.ts    From np-ui-lib with MIT License 4 votes vote down vote up
@Component({
  selector: "np-file-upload",
  templateUrl: "./np-file-upload.component.html",
  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.Default,
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => NpFileUploadComponent),
      multi: true,
    },
    {
      provide: NG_VALIDATORS,
      useExisting: forwardRef(() => NpFileUploadComponent),
      multi: true,
    },
  ],
})
export class NpFileUploadComponent implements ControlValueAccessor, Validator {
  private static controlCount = 1;

  @Input() multiple: boolean;
  @Input() extensions: string;
  @Input() accept: string;
  @Input() size: number;
  @Input() totalSize: number;
  @Input() maxFiles: number;
  @Input() uploadButtonLabel: string;
  @Input() showFileSize: boolean = true;
  @Input() readOnly: boolean;
  @Input() autoFocus: boolean;
  @Input() tabIndex: number;
  @Input() styleClass: string;
  @Input() inputId: string = `np-file-upload_${NpFileUploadComponent.controlCount++}`;

  @Output() onChange: EventEmitter<File[]> = new EventEmitter();
  @Output() onFocus: EventEmitter<any> = new EventEmitter();
  @Output() onBlur: EventEmitter<any> = new EventEmitter();

  @ViewChild("fileUploadInput") fileUploadInput: ElementRef;
  @ViewChild("control") inputViewChild: ElementRef;

  innerValue: File[];
  isDisabled: boolean = false;
  focused: boolean = false;
  private onChangeCallback: (_: any) => void = () => { };
  private onTouchedCallback: () => void = () => { };

  get value(): File[] {
    return this.innerValue ? this.innerValue : null;
  }

  set value(v: File[]) {
    if (v !== this.innerValue) {
      this.innerValue = v;
      this.onChangeCallback(v);
      this.onChange.emit(v);
    }
  }

  writeValue(v: File[]): void {
    if (v !== this.innerValue) {
      this.innerValue = v;
    }
  }

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

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

  setDisabledState?(isDisabled: boolean): void {
    this.isDisabled = isDisabled;
  }

  validate(control: FormControl): any {
    const value = control.value || [];
    if (this.extensions) {
      let isInValidExtension = false;
      const exts = this.extensions.split(",");
      value.forEach((element: any) => {
        if (exts.indexOf(element.name.split(".")[1]) === -1) {
          isInValidExtension = true;
        }
      });
      if (isInValidExtension) {
        return { extensions: { valid: false } };
      }
    }
    if (this.size) {
      let isInValidSize = false;
      value.forEach((element: any) => {
        if (element.size > this.size) {
          isInValidSize = true;
        }
      });
      if (isInValidSize) {
        return { size: { valid: false } };
      }
    }
    if (this.multiple && this.totalSize) {
      let totalSize = 0;
      value.forEach((element: any) => {
        totalSize = totalSize + element.size;
      });
      if (totalSize > this.totalSize) {
        return { totalSize: { valid: false } };
      }
    }
    if (this.maxFiles) {
      if (value.length > this.maxFiles) {
        return { maxFiles: { valid: false } };
      }
    }
  }

  focus(): void {
    this.inputViewChild.nativeElement.focus();
  }

  _clear(): void {
    if (this.isDisabled || this.readOnly) {
      return;
    }
    this.value = null;
  }

  _onFileSelected($event: any): void {
    if (this.isDisabled || this.readOnly) {
      return;
    }
    if (this.multiple) {
      const newFiles = Array.from<File>($event.target.files);
      if (newFiles.length > 0) {
        if (this.value && this.value.length > 0) {
          this.value = this.value.concat(newFiles);
        } else {
          this.value = newFiles;
        }
      }
    } else {
      this.value = Array.from<File>($event.target.files);
    }
    this.fileUploadInput.nativeElement.value = "";
  }

  _formatBytes(file: File, decimals = 2): string {
    const bytes = file.size;
    if (bytes === 0) {
      return "0 Bytes";
    }
    const k = 1024;
    const dm = decimals < 0 ? 0 : decimals;
    const sizes = ["Bytes", "KB", "MB", "GB"];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i];
  }

  _remove(idx: number): void {
    this.value = this.value.filter((element, index) => index !== idx);
  }

  _onBlur($event: any): void {
    this.focused = false;
    this.onTouchedCallback();
    this.onBlur.emit($event);
  }

  _onFocus($event: any): void {
    this.focused = true;
    this.onFocus.emit($event);
  }

  _getLabel(): string {
    return this.uploadButtonLabel
      ? this.uploadButtonLabel
      : this.multiple
        ? "Choose_Files"
        : "Choose_File";
  }

  _getInputId(): string {
    return this.inputId + "_input";
  }
}
Example #10
Source File: np-input-text.component.ts    From np-ui-lib with MIT License 4 votes vote down vote up
@Component({
  selector: "np-input-text",
  templateUrl: "./np-input-text.component.html",
  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.Default,
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => NpInputTextComponent),
      multi: true,
    },
    {
      provide: NG_VALIDATORS,
      useExisting: forwardRef(() => NpInputTextComponent),
      multi: true,
    },
  ],
})
export class NpInputTextComponent implements ControlValueAccessor, Validator {
  private static controlCount = 1;

  @Input() type: string = "text";
  @Input() minLength: number;
  @Input() maxLength: number;
  @Input() pattern: string;
  @Input() prefixLabel: string;
  @Input() suffixLabel: string;
  @Input() mask: string;
  @Input() placeholder: string = "";
  @Input() readOnly: boolean;
  @Input() autoFocus: boolean;
  @Input() tabIndex: number;
  @Input() styleClass: string;
  @Input() inputId: string = `np-input-text_${NpInputTextComponent.controlCount++}`;

  @Output() onChange: EventEmitter<any> = new EventEmitter();
  @Output() onFocus: EventEmitter<any> = new EventEmitter();
  @Output() onBlur: EventEmitter<any> = new EventEmitter();

  @ViewChild("control") inputViewChild: ElementRef;

  innerValue: string;
  isDisabled = false;
  focused = false;

  private onChangeCallback: (_: any) => void = () => { };
  private onTouchedCallback: () => void = () => { };

  get value(): string {
    return this.innerValue ? this.innerValue : null;
  }

  set value(v: string) {
    if (v !== this.innerValue) {
      this.innerValue = v;
      this.onChangeCallback(v);
      this.onChange.emit(v);
    }
  }

  writeValue(v: string): void {
    if (v !== this.innerValue) {
      this.innerValue = v;
    }
  }

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

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

  setDisabledState?(isDisabled: boolean): void {
    this.isDisabled = isDisabled;
  }

  validate(): any {
    if (
      this.minLength !== undefined &&
      this.value &&
      this.value.length < this.minLength
    ) {
      return {
        minLength: {
          valid: false,
        },
      };
    }
    if (
      this.maxLength !== undefined &&
      this.value &&
      this.value.length > this.maxLength
    ) {
      return {
        maxLength: {
          valid: false,
        },
      };
    }
    if (this.pattern) {
      const regex = new RegExp(this.pattern);
      if (this.value && !regex.test(this.value.toString())) {
        return {
          pattern: {
            valid: false,
          },
        };
      }
    }
  }

  focus(): void {
    this.inputViewChild.nativeElement.focus();
  }

  _onInputChange(event: any): void {
    this.value = event.target.value;
  }

  _onBlur($event: any): void {
    this.focused = false;
    this.onTouchedCallback();
    this.onBlur.emit($event);
  }

  _onFocus($event: any): void {
    this.focused = true;
    this.onFocus.emit($event);
  }
}
Example #11
Source File: np-number-box.component.ts    From np-ui-lib with MIT License 4 votes vote down vote up
@Component({
  selector: "np-number-box",
  templateUrl: "./np-number-box.component.html",
  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.Default,
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => NpNumberBoxComponent),
      multi: true,
    },
    {
      provide: NG_VALIDATORS,
      useExisting: forwardRef(() => NpNumberBoxComponent),
      multi: true,
    },
  ],
})
export class NpNumberBoxComponent implements ControlValueAccessor, Validator {
  private static controlCount = 1;

  @Input() steps: number = 1;
  @Input() min: number;
  @Input() max: number;
  @Input() pattern: string;
  @Input() prefixLabel: string;
  @Input() suffixLabel: string;
  @Input() showControls: boolean = true;
  @Input() placeholder: string = "";
  @Input() readOnly: boolean;
  @Input() autoFocus: boolean;
  @Input() tabIndex: number;
  @Input() styleClass: string;
  @Input() inputId: string = `np-number-box_${NpNumberBoxComponent.controlCount++}`;

  @Output() onChange: EventEmitter<any> = new EventEmitter();
  @Output() onFocus: EventEmitter<any> = new EventEmitter();
  @Output() onBlur: EventEmitter<any> = new EventEmitter();

  @ViewChild("control") inputViewChild: ElementRef;

  innerValue: number;
  isDisabled: boolean = false;
  focused: boolean = false;
  private timeout: any;
  private onChangeCallback: (_: any) => void = () => { };
  private onTouchedCallback: () => void = () => { };

  get value(): number {
    return this.innerValue !== undefined ? this.innerValue : null;
  }

  set value(v: number) {
    if (v !== this.innerValue) {
      this.innerValue = v;
      this.onChangeCallback(v);
      this.onChange.emit(v);
    }
  }

  writeValue(v: number): void {
    if (v !== this.innerValue) {
      this.innerValue = v;
    }
  }

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

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

  setDisabledState?(isDisabled: boolean): void {
    this.isDisabled = isDisabled;
  }

  validate(): any {
    if (this.min !== undefined && this.value < this.min) {
      return {
        min: {
          valid: false,
        },
      };
    }
    if (this.max !== undefined && this.value > this.max) {
      return {
        max: {
          valid: false,
        },
      };
    }
    if (this.pattern) {
      const regex = new RegExp(this.pattern);
      if (this.value && !regex.test(this.value.toString())) {
        return {
          pattern: {
            valid: false,
          },
        };
      }
    }
  }

  focus(): void {
    this.inputViewChild.nativeElement.focus();
  }

  _add(): void {
    if (this.isDisabled || this.readOnly) {
      return;
    }
    this.value = this.value + this.steps;
  }

  _minus(): void {
    if (this.isDisabled || this.readOnly) {
      return;
    }
    this.value = this.value - this.steps;
  }

  _onMouseDownPlus(): void {
    const that = this;
    this._clearTimeout();
    this.timeout = setTimeout(() => {
      that._onMouseDownPlus();
    }, 200);
    that._add();
  }

  _onMouseUpPlus(): void {
    this._clearTimeout();
    this.inputViewChild.nativeElement.focus();
  }

  _onMouseDownMinus(): void {
    const that = this;
    this._clearTimeout();
    this.timeout = setTimeout(() => {
      that._onMouseDownMinus();
    }, 200);
    that._minus();
  }

  _onMouseUpMinus(): void {
    this._clearTimeout();
    this.inputViewChild.nativeElement.focus();
  }

  _clearTimeout(): void {
    if (this.timeout) {
      clearTimeout(this.timeout);
    }
  }

  _onInputChange(event: any): void {
    if (isNaN(parseFloat(event.target.value))) {
      this.value = null;
    } else {
      this.value = Number(event.target.value);
    }
  }

  _onBlur($event: any): void {
    this.focused = false;
    this.onTouchedCallback();
    this.onBlur.emit($event);
  }

  _onFocus($event: any): void {
    this.focused = true;
    this.onFocus.emit($event);
  }
}
Example #12
Source File: np-rich-text.component.ts    From np-ui-lib with MIT License 4 votes vote down vote up
@Component({
  selector: "np-rich-text",
  templateUrl: "./np-rich-text.component.html",
  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.Default,
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => NpRichTextComponent),
      multi: true,
    },
    {
      provide: NG_VALIDATORS,
      useExisting: forwardRef(() => NpRichTextComponent),
      multi: true,
    },
  ],
})
export class NpRichTextComponent implements ControlValueAccessor, Validator {
  private static controlCount = 1;

  @Input() minLength: number;
  @Input() maxLength: number;
  @Input() config: string[];
  @Input() fonts: string[];
  @Input() height: number;
  @Input() readOnly: boolean;
  @Input() autoFocus: boolean;
  @Input() tabIndex: number;
  @Input() styleClass: string;
  @Input() inputId: string = `np-rich-text_${NpRichTextComponent.controlCount++}`;
  @Output() onChange: EventEmitter<any> = new EventEmitter();
  @Output() onFocus: EventEmitter<any> = new EventEmitter();
  @Output() onBlur: EventEmitter<any> = new EventEmitter();

  @ViewChild("control") inputViewChild: ElementRef;
  @ViewChild("createLinkPopover") createLinkPopover: NpPopoverDirective;
  @ViewChild("foreColorPopover") foreColorPopover: NpPopoverDirective;
  @ViewChild("backColorPopover") backColorPopover: NpPopoverDirective;

  innerValue: string;
  isDisabled: boolean = false;
  focused: boolean = false;
  isBold: boolean = false;
  isItalic: boolean = false;
  isUnderline: boolean = false;
  isBlockquote: boolean = false;
  isStrikethrough: boolean = false;
  currentFormat: string = "no value";
  currentFont: string = "no value";
  currentfontsize: string = "no value";
  linkUrl: string;
  currentSelectionRange: Range;
  foreColor: string;
  backColor: string;

  private onChangeCallback: (_: any) => void = () => { };
  private onTouchedCallback: () => void = () => { };

  constructor(private el: ElementRef) {
    this.config = [
      "bold",
      "italic",
      "underline",
      "strikethrough",
      "removeformat",
      "formatblock",
      "blockquote",
      "fontname",
      "fontsize",
      "forecolor",
      "backcolor",
      "subscript",
      "superscript",
      "justifyleft",
      "justifycenter",
      "justifyright",
      "indent",
      "outdent",
      "insertunorderedlist",
      "insertorderedlist",
      "createlink",
      "undo",
      "redo",
    ];
    this.fonts = ["Arial", "Arial Black", "Courier New", "Times New Roman"];
  }

  get value(): string {
    return this.innerValue ? this.innerValue : null;
  }

  set value(v: string) {
    if (v !== this.innerValue) {
      this.innerValue = v;
      this.onChangeCallback(v);
      this.onChange.emit(v);
    }
  }

  writeValue(v: string): void {
    if (v !== this.innerValue) {
      this.innerValue = v;
      if (this.inputViewChild && v) {
        this.inputViewChild.nativeElement.innerHTML = v;
      }
    }
  }

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

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

  setDisabledState?(isDisabled: boolean): void {
    this.isDisabled = isDisabled;
  }

  validate(): any {
    var text = this.el.nativeElement.querySelector(".np-rich-text-input")
      .textContent;
    if (this.minLength !== undefined && text && text.length < this.minLength) {
      return {
        minLength: {
          valid: false,
        },
      };
    }
    if (this.maxLength !== undefined && text && text.length > this.maxLength) {
      return {
        maxLength: {
          valid: false,
        },
      };
    }
  }

  focus(): void {
    this.inputViewChild.nativeElement.focus();
  }

  _onInputChange(event: any): void {
    this.value = event.target.innerHTML;
  }

  _onBlur($event: any): void {
    this.focused = false;
    this.onTouchedCallback();
    this.onBlur.emit($event);
  }

  _onFocus($event: any): void {
    this.focused = true;
    this.onFocus.emit($event);
  }

  _formatDoc(sCmd: string, sValue: any): void {
    document.execCommand(sCmd, false, sValue);
    this.focus();
  }

  _formatBlock(sCmd: string, sValue: any): void {
    if (sValue === "no value") {
      return;
    }
    this._formatDoc(sCmd, sValue);
    setTimeout(() => {
      this.currentFormat = "no value";
      this.currentFont = "no value";
      this.currentfontsize = "no value";
    }, 100);
  }

  _showForeColorOverlay(): void {
    if (!this.focused) {
      this.focus();
    }
    if (document.getSelection() && document.getSelection().getRangeAt) {
      this.currentSelectionRange = document.getSelection().getRangeAt(0);
    }
    let colour = document.queryCommandValue("foreColor");
    if (colour.indexOf("rgb") > -1) {
      colour = this._changeRGBToHex(colour);
    }
    if (colour.indexOf("transparent") > -1) {
      colour = null;
    }
    this.foreColor = colour;
  }

  _changeForeColor(color: any): void {
    if (this.currentSelectionRange) {
      document.getSelection().removeAllRanges();
      document.getSelection().addRange(this.currentSelectionRange);
      this.foreColor = color;
      if (color) {
        this._formatDoc("foreColor", color);
      } else {
        document.execCommand("removeformat", false, "foreColor");
      }
      this.currentSelectionRange = null;
    }
    this.foreColorPopover.close();
  }

  _showBackColorOverlay(): void {
    if (!this.focused) {
      this.focus();
    }
    if (document.getSelection() && document.getSelection().getRangeAt) {
      this.currentSelectionRange = document.getSelection().getRangeAt(0);
    }
    let colour = document.queryCommandValue("backColor");
    if (colour.indexOf("rgb") > -1) {
      colour = this._changeRGBToHex(colour);
    }
    if (colour.indexOf("transparent") > -1) {
      colour = null;
    }
    this.backColor = colour;
  }

  _changeBackColor(color: any): void {
    if (this.currentSelectionRange) {
      document.getSelection().removeAllRanges();
      document.getSelection().addRange(this.currentSelectionRange);
      this.backColor = color;
      if (color) {
        this._formatDoc("backColor", color);
      } else {
        document.execCommand("removeformat", false, "backColor");
      }
      this.currentSelectionRange = null;
    }
    this.backColorPopover.close();
  }

  _onCloseOverlays(): void {
    if (this.currentSelectionRange) {
      document.getSelection().removeAllRanges();
      document.getSelection().addRange(this.currentSelectionRange);
      this.currentSelectionRange = null;
    }
    this.focus();
  }

  _showCreateLink(): void {
    if (!this.focused) {
      this.focus();
    }
    if (document.getSelection() && document.getSelection().getRangeAt) {
      this.currentSelectionRange = document.getSelection().getRangeAt(0);
    }
    this.linkUrl = "https://";
  }

  _createLink(): void {
    if (this.currentSelectionRange) {
      document.getSelection().removeAllRanges();
      document.getSelection().addRange(this.currentSelectionRange);
      if (this.linkUrl) {
        this._formatDoc("createlink", this.linkUrl);
      }
      this.currentSelectionRange = null;
    }
    this.createLinkPopover.close();
  }

  _closeCreateLinkOverlay(): void {
    this.createLinkPopover.close();
  }

  _changeRGBToHex(val: any): string {
    const rgb = val
      .replace("rgb", "")
      .replace("rgba", "")
      .replace("(", "")
      .replace(")", "")
      .replace(" ", "");
    const rgbAray = rgb.split(",");
    return this._rgbToHex(
      Number(rgbAray[0]),
      Number(rgbAray[1]),
      Number(rgbAray[2])
    );
  }

  _rgbToHex(r: any, g: any, b: any): string {
    const red = this._convertNumberToHex(r);
    const green = this._convertNumberToHex(g);
    const blue = this._convertNumberToHex(b);
    return `#${red}${green}${blue}`;
  }

  _convertNumberToHex(num: any): string {
    let hex = Number(num).toString(16);
    if (hex.length < 2) {
      hex = `0${hex}`;
    }
    return hex;
  }

  _isAllowed(permission: string): boolean {
    return this.config.indexOf(permission) > -1;
  }
}
Example #13
Source File: np-textarea.component.ts    From np-ui-lib with MIT License 4 votes vote down vote up
@Component({
  selector: "np-textarea",
  templateUrl: "./np-textarea.component.html",
  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.Default,
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => NpTextareaComponent),
      multi: true,
    },
    {
      provide: NG_VALIDATORS,
      useExisting: forwardRef(() => NpTextareaComponent),
      multi: true,
    },
  ],
})
export class NpTextareaComponent implements ControlValueAccessor, Validator {
  private static controlCount = 1;

  @Input() rows: number;
  @Input() cols: number;
  @Input() resize: boolean = true;
  @Input() minLength: number;
  @Input() maxLength: number;
  @Input() placeholder: string = "";
  @Input() readOnly: boolean;
  @Input() autoFocus: boolean;
  @Input() tabIndex: number;
  @Input() styleClass: string;
  @Input() inputId: string = `np-textarea_${NpTextareaComponent.controlCount++}`;

  @Output() onChange: EventEmitter<any> = new EventEmitter();
  @Output() onFocus: EventEmitter<any> = new EventEmitter();
  @Output() onBlur: EventEmitter<any> = new EventEmitter();

  @ViewChild("control") inputViewChild: ElementRef;

  innerValue: string;
  isDisabled: boolean = false;
  focused: boolean = false;

  private onChangeCallback: (_: any) => void = () => { };
  private onTouchedCallback: () => void = () => { };

  get value(): string {
    return this.innerValue ? this.innerValue : null;
  }

  set value(v: string) {
    if (v !== this.innerValue) {
      this.innerValue = v;
      this.onChangeCallback(v);
      this.onChange.emit(v);
    }
  }

  writeValue(v: string): void {
    if (v !== this.innerValue) {
      this.innerValue = v;
    }
  }

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

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

  setDisabledState?(isDisabled: boolean): void {
    this.isDisabled = isDisabled;
  }

  validate(): any {
    if (
      this.minLength !== undefined &&
      this.value &&
      this.value.length < this.minLength
    ) {
      return {
        minLength: {
          valid: false,
        },
      };
    }
    if (
      this.maxLength !== undefined &&
      this.value &&
      this.value.length > this.maxLength
    ) {
      return {
        maxLength: {
          valid: false,
        },
      };
    }
  }

  focus(): void {
    this.inputViewChild.nativeElement.focus();
  }

  _onInputChange(event: any): void {
    this.value = event.target.value;
  }

  _onBlur($event: any): void {
    this.focused = false;
    this.onTouchedCallback();
    this.onBlur.emit($event);
  }

  _onFocus($event: any): void {
    this.focused = true;
    this.onFocus.emit($event);
  }
}