Search code examples
javascriptangularangular-ngmodel

Input accept numbers-only custom directive


I'm trying to create a custom directive in Angular2 so it accepts numbers-only /^\d+$/. So far I have created a directive which is kind of achieves what I need. But...

The Problem:

  1. When I try to type inside the <input> tag the character appears for a second and then disappears.

  2. The [(ngModel)] which is bound to the element, updates on typing readily (while typing a number), but when a character is typed 'a || b || c, etc' it get stored in ngModel and gets updated on typing a number.

  3. In this way I cannot go over the <input> characters by arrow keys, as it is bound to keyup.

Component:

export class AppComponent {
  myValue = 123;
}

HTML:

<input type="text" name="color" [(ngModel)]="myValue" numbers-only/> <br>
{{myValue}}

Directive:

@Directive({
  selector: '[numbers-only]', 
    host: {
        '(keyup)' : 'onInputChange()'
    }
})
export class UpperCaseDirective {
  private oldVal = '';
  @Input() ngModel: any;

  constructor(private el: ElementRef) { }

  ngOnInit() {
    this.oldVal = this.ngModel || '';
  }

  onInputChange() {
    console.log(this.ngModel, !isNaN(this.ngModel));
    var reg = /^\d+$/;
    if (reg.test(this.ngModel)) {      
      this.el.nativeElement.value = this.ngModel;
      this.oldVal = this.ngModel;
    } else {
      this.el.nativeElement.value = this.oldVal;
    }
  }

}

Coming form a Angular1 background, I find it very hard to write so much code for a simple number only <input>, ng-pattern would do the trick there.

Kindly suggest a way to achieve this OR any other better solution is also welcomed.


Solution

  • use keypress event

    @HostListener('keypress') onkeypress(e){
            let event = e || window.event;
            if(event){
              return this.isNumberKey(event);
            }
          }
    
      isNumberKey(event){
         let charCode = (event.which) ? event.which : event.keyCode;
         if (charCode > 31 && (charCode < 48 || charCode > 57)){
            return false;
         }
         return true;
      }
    
    
    <input type="text" name="color" [(ngModel)]="myValue" appUpperCase/>