Home > Software engineering >  Why the [value] is not working when using the directive for mobile number?
Why the [value] is not working when using the directive for mobile number?

Time:12-02

I am using the directive to validate the mobile number input

import { Directive, ElementRef, HostListener, Input } from '@angular/core';

@Directive({
  selector: '[mobileNumber]'
})
export class MobileNumberDirective {

  @Input()
  public value: any;

  constructor(private el: ElementRef) { }

  @HostListener('keypress', ['$event'])
    onKeyDown(event: KeyboardEvent) {

        var inp = String.fromCharCode(event.keyCode);
        if (/[0-9]/.test(inp)) {
            return true;
        } else {
            if (event.keyCode == 8 || (event.keyCode == 43 && this.value == '')) {
                return true;
            } else {
                event.preventDefault();
                return false;
            }
        }
    }

}

The input field is this :

<input
       type="text"
       placeholder="Search Mobile"
       autocomplete="off"
       [value]="'1111199999'"
       mobileNumber
/>

here, the [value] is not working when the directive is applied but working fine without it.

CodePudding user response:

You are using bi-directional in Ui, So once you assign the direct value (number or string) will not work.

<input
       type="text"
       placeholder="Search Mobile"
       autocomplete="off"
       [value]="value" <-- bind your property
       mobileNumber
/>

Please refer the Link

I hope this solution is clear to you

CodePudding user response:

You are not indicate to your directive that the element show the "value" (you can see more clear if you choose as name of your input, e.g. "myValue")

You can implements OnInit and write

ngOnInit{
  this.el.nativeElement.value=this.value;
}

BTW, you're using a directive not for validate, else to avoid keydown a "not number".

We can use the ngOnInit also to check at first if value fullfilled the condition.

ngOnInit{
  if (this.value)
       this.el.nativeElement.value=this.value.replace(/[^0-9]/g,'')
}

Well, you can also use [(ngModel)] to have a two-binding to get the value of the variable (also you can use [attr.value] instead of [value] and remove the @Input() valuefrom your directive

To use either, [(ngModel)] or [value] you directive can be like

  @Input()
  public value: any;

  //see in constructor how inject a "NgControl"
  constructor(private el: ElementRef,@Optional() private control:NgControl) {}

  @HostListener('keypress', ['$event'])
    onKeyDown(event: KeyboardEvent) {
       ...
    }

ngOnInit(){
    setTimeout(()=>{
        if (this.control)
            this.control.control.setValue(
                        this.control.value?this.control.value.replace(/[^0-9]/g,''):
            '')
        else
            this.el.nativeElement.value=this.value?this.value.replace(/[^0-9]/g,''):
            ''
    })
}

stackblitz

CodePudding user response:

Please use RegexFormate Validation and after set [maxlength]="10" like this this is good option to add validation

Example :

 <div >
          <mat-form-field  appearance="outline">
            <mat-label>Mobile No (First)</mat-label>
            <input matInput [formControl]="mobile1" [maxlength]="10" appRegexFormate regexType="number"
                   autoComplete='off' [(ngModel)]="merchantModelAdd.mobile1" required>
            <mat-error *ngIf="mobile1.hasError('required')">Mobile No (First) cannot be
              empty
            </mat-error>
            <mat-error *ngIf="mobile1.hasError('pattern')">Invalid mobile No (First)
            </mat-error>
          </mat-form-field>
        </div>

Regex Class

import {Directive, ElementRef, HostListener, Input} from '@angular/core';

@Directive({
  selector: '[appRegexFormate]'
})
export class RegexFormateDirective {
  @Input('regexType') numericType: string;
  private regex = {
    number: new RegExp(/^\d $/),
    letter_only: new RegExp(/^[a-zA-Z] $/g),
    letter_space: new RegExp(/^[a-zA-Z ] $/g),
    letter_num: new RegExp(/^[a-zA-Z0-9] $/g),
    letter_num_space: new RegExp(/^[a-zA-Z0-9 ] $/g),
    letter_num_special: new RegExp(/^[a-zA-Z0-9-@#$%^&*!()_ \-=\[\]{};':"\\|,.<>\/?] $/g),
    remark: new RegExp(/^[a-zA-Z0-9-@#$%^&*!()_ \-=\[\]{};:\\,.<>\/? \n] $/g),
    url:  new RegExp(/^[a-zA-Z\-] $/g),
    decimal: new RegExp(/^[0-9] (\.[0-9]*){0,1}$/g),
    email: new RegExp(/^[a-zA-Z0-9@_.] $/g),
    long_lat_number: new RegExp(/^[0-9]{0,3}(\.[0-9]{0,5})?$/g)

  };
  private specialKeys = {
    number: ['Backspace', 'Tab', 'End', 'Home', 'ArrowLeft', 'ArrowRight'],
    letter_only: [ 'Backspace', 'Tab', 'End', 'Home', 'ArrowLeft', 'ArrowRight' ],
    letter_space: [ 'Backspace', 'Tab', 'End', 'Home', 'ArrowLeft', 'ArrowRight' ],
    letter_num: [ 'Backspace', 'Tab', 'End', 'Home', 'ArrowLeft', 'ArrowRight' ],
    letter_num_space: [ 'Backspace', 'Tab', 'End', 'Home', 'ArrowLeft', 'ArrowRight' ],
    letter_num_special: [ 'Backspace', 'Tab', 'End', 'Home', 'ArrowLeft', 'ArrowRight' ],
    remark: [ 'Backspace', 'Tab', 'End', 'Home', 'ArrowLeft', 'ArrowRight'],
    url: [ 'Backspace', 'Tab', 'End', 'Home', 'ArrowLeft', 'ArrowRight' ],
    decimal: [ 'Backspace', 'Tab', 'End', 'Home', 'ArrowLeft', 'ArrowRight' ],
    email: [ 'Backspace', 'Tab', 'End', 'Home', 'ArrowLeft', 'ArrowRight' ],
    long_lat_number: [ 'Backspace', 'Tab', 'End', 'Home', 'ArrowLeft', 'ArrowRight' ],
  };

  constructor(private elementRef: ElementRef) {
  }

  @HostListener('keydown', ['$event'])
  onKeyDown(event: KeyboardEvent) {
    if (this.specialKeys[this.numericType].indexOf(event.key) !== -1) {
      return;
    }
    const current: string = this.elementRef.nativeElement.value;
    const next: string = current.concat(event.key);
    if (next && !String(next).match(this.regex[this.numericType])) {
      event.preventDefault();
    }
  }

  @HostListener('click', ['$event'])
  onKeyDown2(event: KeyboardEvent) {
    const current: string = this.elementRef.nativeElement.value;
    const element = this.elementRef.nativeElement;
    if (current) {
      if (!String(current).match(this.regex[this.numericType])) {
        this.elementRef.nativeElement.value = '';
        setTimeout(function (evet) {
          element.click();
        }, 100);
      }
    }
  }

  @HostListener('paste', ['$event']) blockPaste(e: KeyboardEvent) {
    e.preventDefault();
  }
}

use like this this is best option

  • Related