@angular/forms#NG_VALIDATORS TypeScript Examples

The following examples show how to use @angular/forms#NG_VALIDATORS. 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: url-validator.directive.ts    From one-platform with MIT License 6 votes vote down vote up
@Directive({
  selector: '[urlValidator][ngModel]',
  providers: [
    { provide: NG_VALIDATORS, useExisting: UrlValidatorDirective, multi: true },
  ],
})
export class UrlValidatorDirective {
  validator: ValidatorFn;
  constructor() {
    this.validator = this.urlValidator();
  }

  validate(c: FormControl) {
    return this.validator(c);
  }

  urlValidator(): ValidatorFn {
    return (control: FormControl) => {
      const url = control.value;
      try {
        new URL(url);
        return null;
      } catch (e) {
        return { urlValidator: { valid: false } };
      }
    };
  }
}
Example #2
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 #3
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 #4
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 #5
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 #6
Source File: validators.directive.ts    From workflow-editor with Educational Community License v2.0 6 votes vote down vote up
@Directive({
  selector: '[appOpIfConditionValidator]',
  providers: [
    {
      provide: NG_VALIDATORS,
      useExisting: OpIfConditionValidatorDirective, multi: true
    }]
})
export class OpIfConditionValidatorDirective {

  constructor() {
  }

  validate(control: AbstractControl): {[key: string]: any} {
    const parser: Parser = new Parser(
      Grammar.fromCompiled(grammar),
      { keepHistory: true }
    );
    try {
      parser.feed(control.value);
      return null;
    } catch (err) {
      return {invalidIfCond: {notvalid: true, msg: err.message.split("Instead")[0]}};
    }
  }

}
Example #7
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 #8
Source File: color-input.component.ts    From angular-material-components with MIT License 5 votes vote down vote up
MAT_COLORPICKER_VALIDATORS: any = {
  provide: NG_VALIDATORS,
  useExisting: forwardRef(() => NgxMatColorPickerInput),
  multi: true
}
Example #9
Source File: datetime-input.ts    From angular-material-components with MIT License 5 votes vote down vote up
MAT_DATEPICKER_VALIDATORS: any = {
    provide: NG_VALIDATORS,
    useExisting: forwardRef(() => NgxMatDatetimeInput),
    multi: true
}
Example #10
Source File: datetime-input.ts    From ngx-mat-datetime-picker with MIT License 5 votes vote down vote up
MAT_DATEPICKER_VALIDATORS: any = {
    provide: NG_VALIDATORS,
    useExisting: forwardRef(() => NgxMatDatetimeInput),
    multi: true
}
Example #11
Source File: route-selector.component.ts    From fyle-mobile-app with MIT License 4 votes vote down vote up
@Component({
  selector: 'app-route-selector',
  templateUrl: './route-selector.component.html',
  styleUrls: ['./route-selector.component.scss'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      multi: true,
      useExisting: RouteSelectorComponent,
    },
    {
      provide: NG_VALIDATORS,
      useExisting: RouteSelectorComponent,
      multi: true,
    },
  ],
})
export class RouteSelectorComponent implements OnInit, ControlValueAccessor, OnDestroy, OnChanges, DoCheck {
  @Input() unit: 'KM' | 'MILES';

  @Input() mileageConfig;

  @Input() isDistanceMandatory;

  @Input() isAmountDisabled;

  @Input() txnFields;

  @Input() formInitialized;

  @Input() isConnected;

  @Input() recentlyUsedMileageLocations: {
    recent_start_locations?: string[];
    recent_end_locations?: string[];
    recent_locations?: string[];
  };

  skipRoundTripUpdate = false;

  onChangeSub: Subscription;

  form: FormGroup = this.fb.group({
    mileageLocations: new FormArray([]),
    distance: [, Validators.required],
    roundTrip: [],
  });

  private ngControl: NgControl;

  constructor(private fb: FormBuilder, private modalController: ModalController, private injector: Injector) {}

  get mileageLocations() {
    return this.form.controls.mileageLocations as FormArray;
  }

  onTouched = () => {};

  ngDoCheck() {
    if (this.ngControl.touched) {
      this.form.markAllAsTouched();
    }
  }

  ngOnDestroy(): void {
    this.onChangeSub.unsubscribe();
  }

  customDistanceValidator(control: AbstractControl) {
    const passedInDistance = control.value && +control.value;
    if (passedInDistance !== null) {
      return passedInDistance > 0
        ? null
        : {
            invalidDistance: true,
          };
    }
  }

  ngOnChanges(changes: SimpleChanges): void {
    if (changes.mileageConfig && !isEqual(changes.mileageConfig.previousValue, changes.mileageConfig.currentValue)) {
      this.onMileageConfigChange();
    }

    if (changes.txnFields && !isEqual(changes.txnFields.previousValue, changes.txnFields.currentValue)) {
      this.onTxnFieldsChange();
    }
  }

  onTxnFieldsChange() {
    const keyToControlMap: { [id: string]: AbstractControl } = {
      distance: this.form.controls.distance,
    };

    for (const control of Object.values(keyToControlMap)) {
      control.clearValidators();
      control.updateValueAndValidity();
    }

    for (const txnFieldKey of intersection(['distance'], Object.keys(this.txnFields))) {
      const control = keyToControlMap[txnFieldKey];

      if (this.txnFields[txnFieldKey].is_mandatory) {
        if (txnFieldKey === 'distance') {
          control.setValidators(
            this.isConnected ? Validators.compose([Validators.required, this.customDistanceValidator]) : null
          );
        }
      }
      control.updateValueAndValidity();
    }

    this.form.updateValueAndValidity();
  }

  onMileageConfigChange() {
    this.form.controls.mileageLocations.clearValidators();
    this.form.controls.mileageLocations.updateValueAndValidity();
    if (this.mileageConfig.location_mandatory) {
      this.form.controls.mileageLocations.setValidators(Validators.required);
    }
    this.form.controls.mileageLocations.updateValueAndValidity();
    this.form.updateValueAndValidity();
  }

  writeValue(value): void {
    if (value) {
      if (value.mileageLocations) {
        value.mileageLocations.forEach((location) => {
          this.mileageLocations.push(
            new FormControl(location, this.mileageConfig.location_mandatory && Validators.required)
          );
        });
        if (value.mileageLocations.length === 1) {
          this.mileageLocations.push(
            new FormControl(null, this.mileageConfig.location_mandatory && Validators.required)
          );
        }
      }

      this.form.patchValue({
        distance: value.distance,
        roundTrip: value.roundTrip,
      });
    }
  }

  registerOnChange(onChange): void {
    this.onChangeSub = this.form.valueChanges.subscribe(onChange);
  }

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

  setDisabledState?(disabled: boolean): void {
    if (disabled) {
      this.form.disable();
    } else {
      this.form.enable();
    }
  }

  ngOnInit() {
    this.ngControl = this.injector.get(NgControl);

    this.form.controls.roundTrip.valueChanges.subscribe((roundTrip) => {
      if (!this.skipRoundTripUpdate) {
        if (this.formInitialized) {
          if (this.form.value.distance) {
            if (roundTrip) {
              this.form.controls.distance.setValue((+this.form.value.distance * 2).toFixed(2));
            } else {
              this.form.controls.distance.setValue((+this.form.value.distance / 2).toFixed(2));
            }
          }
        }
      } else {
        this.skipRoundTripUpdate = false;
      }
    });
  }

  async openModal() {
    const selectionModal = await this.modalController.create({
      component: RouteSelectorModalComponent,
      componentProps: {
        unit: this.unit,
        mileageConfig: this.mileageConfig,
        isDistanceMandatory: this.isDistanceMandatory,
        isAmountDisabled: this.isAmountDisabled,
        txnFields: this.txnFields,
        value: this.form.value,
        recentlyUsedMileageLocations: this.recentlyUsedMileageLocations,
      },
    });

    await selectionModal.present();

    const { data } = await selectionModal.onWillDismiss();

    if (data) {
      this.skipRoundTripUpdate = true;
      this.mileageLocations.clear({
        emitEvent: false,
      });

      data.mileageLocations.forEach((mileageLocation) => {
        this.mileageLocations.push(
          new FormControl(mileageLocation, this.mileageConfig.location_mandatory && Validators.required)
        );
      });

      this.form.patchValue({
        distance: parseFloat(data.distance),
        roundTrip: data.roundTrip,
      });
    }
  }

  validate(fc: FormControl) {
    if (!this.form.valid) {
      return {
        ...this.form.controls.mileageLocations.errors,
        ...this.form.controls.distance.errors,
      };
    }
    return null;
  }
}
Example #12
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 #13
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 #14
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 #15
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 #16
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);
  }
}