2016-11-06 60 views
0

我想在Angular2中創建一個自定義指令,所以它只接受數字/^\d+$/。到目前爲止,我已經創建了一個指令,它實現了我所需要的。但是......輸入接受數字只有自定義指令

問題:

  1. 當我嘗試了<input>標籤內鍵入的字符出現第二個,然後消失。

  2. [(ngModel)]這是綁定到元素,更新打字容易(同時鍵入一個數字),但是當一個字符輸入「a ||」 b || c等等,它會被存儲在ngModel中,並在輸入數字時得到更新。

  3. 通過這種方式,我不能通過箭頭鍵瀏覽<input>個字符,因爲它必然會與keyup綁定。

組件:

export class AppComponent { 
    myValue = 123; 
} 

HTML:

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

指令:

@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; 
    } 
    } 

} 

即將形成一個Angular1背景,我發現很難爲一個簡單的數字編寫這麼多的代碼只有<input>,ng-pattern會在那裏做伎倆。

請提出一個方法來實現這個或其他更好的解決方案也是受歡迎的。

+0

使用appUpperCase而不是使用大寫。 – Manish

+0

@ user32我的不好,在我的code..typo這裏用作'大寫'..現在改變它。 – yashhy

回答

1

使用按鍵事件

@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/> 
+0

不是@ @Directive'聲明中的'@ HostListener'和'host'屬性是否做同樣的事情? – yashhy

+0

不,兩者都不同,但你可以使用其中任何一個。主機是指令的屬性。 主機:{'(keypress)':'onkeypress(e)'} – Manish

+0

我試圖通過ngModel實現它(因爲擺脫了'charCode'),但它似乎ngModel只更新keyUp..and嘗試通過我的上述代碼實現(使用keyUp)導致延遲(因爲它必須更新UI,然後來到keyUp事件並檢查條件並更改該值)。 – yashhy

0

我不知道你是能夠做到這一點沒有突變的HTML,我可以提出兩個解決方案:

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

或者在組件

動態地做到這一點
ngAfterViewInit() { 
    this.el.nativeElement.type = "number"; 
} 
+0

''在chrome中工作,但不在Mozilla或IE11 +中如果我沒有錯-_-。 Firefox確實允許輸入字母字符! – yashhy

0

您可以創建自定義驗證器並使用Angular 2的Forms API。而不是使用usin g雙向綁定和事件,只需創建FormControl的一個實例並將其鏈接到輸入字段即可。在創建FormControl的一個實例時,爲它分配一個自定義驗證器,即一個將驗證輸入的函數。例如,您可以只允許輸入正數:

function positiveNumberValidator(control: FormControl): any { 
    if (!control.value) return null; 
    const price = parseInt(control.value); 
    return price === null || 
    typeof price === 'number' && 
    price > 0 ? null : {positivenumber: true}; 
} 

如果此函數返回null,則表示該值有效。你可以看到這個例子中的SearchComponent在這裏實現:https://github.com/Farata/angular2typescript/tree/master/chapter8/auction/client/app/components/search

這個例子使用FormBuilder API,但你可以聲明一個變量,實例化對象,並指定驗證:如果你想換

let price: FormControl = new FormControl('', positiveNumberValidator); 

您的驗證成指令,這是可以做到這樣的:

@Directive({
  
    selector: '[numbers-only]',
  
    providers: [{provide: NG_VALIDATORS, 
         useValue: positiveNumberValidator}] 

 })
  
class NumberValidatorDirective {} 
+0

感謝您的回答,我有這種方式嘗試顯示錯誤消息..但在我的情況下,我們必須刪除用戶在''輸入的字符,而不只是顯示錯誤消息。 – yashhy

+0

不確定如果它在所有瀏覽器中的工作方式都一樣,但Chrome甚至不允許在輸入字段中使用此類驗證器輸入字母字符。 –

0

我發現具有一個char(長度= 1)呈現一個char是關鍵。如果我們只是想呈現數字,我們可以爲的preventDefault所有其它鍵,長度爲一,而不是一個號碼(< 48或> 57):

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

@Directive({ 
    selector: '[numbers-only]' 
}) 
export class NumbersOnlyDirective { 
    @HostListener('keydown', ['$event']) 
    keyDownEvent(event: KeyboardEvent) { 
     if (event.key.length === 1 && (event.which < 48 || event.which > 57)) { 
      event.preventDefault(); 
     } 
    } 

} 
相關問題