web-dev-qa-db-fra.com

Angular2 - Champ de saisie pour accepter uniquement les nombres

Dans Angular2, comment masquer un champ de saisie (zone de texte) tel qu’il accepte uniquement les nombres et non les alphabets?

J'ai l'entrée HTML suivante:

<input type="text" *ngSwitchDefault class="form-control" (change)="onInputChange()" [(ngModel)]="config.Value" focus)="handleFocus($event)" (blur)="handleBlur($event)"/>

L'entrée ci-dessus est une entrée de texte générique qui peut être utilisée soit comme un simple champ de texte, soit comme un champ numérique (par exemple, pour indiquer l'année).

Avec angular2, comment puis-je utiliser le même contrôle d’entrée et appliquer une sorte de filtre/masque sur ce champ, de sorte qu’il accepte uniquement les nombres? Quels sont les différents moyens pour y parvenir?

Remarque: je dois y parvenir en utilisant uniquement la zone de texte et en n'utilisant pas le type de numéro d'entrée.

52
Aniruddha Pondhe

Vous pouvez utiliser les directives angular2. Plunkr

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

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

  constructor(private el: ElementRef) { }

  @Input() OnlyNumber: boolean;

  @HostListener('keydown', ['$event']) onKeyDown(event) {
    let e = <KeyboardEvent> event;
    if (this.OnlyNumber) {
      if ([46, 8, 9, 27, 13, 110, 190].indexOf(e.keyCode) !== -1 ||
        // Allow: Ctrl+A
        (e.keyCode === 65 && (e.ctrlKey || e.metaKey)) ||
        // Allow: Ctrl+C
        (e.keyCode === 67 && (e.ctrlKey || e.metaKey)) ||
        // Allow: Ctrl+V
        (e.keyCode === 86 && (e.ctrlKey || e.metaKey)) ||
        // Allow: Ctrl+X
        (e.keyCode === 88 && (e.ctrlKey || e.metaKey)) ||
        // Allow: home, end, left, right
        (e.keyCode >= 35 && e.keyCode <= 39)) {
          // let it happen, don't do anything
          return;
        }
        // Ensure that it is a number and stop the keypress
        if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
            e.preventDefault();
        }
      }
  }
}

et vous devez écrire le nom de la directive dans votre entrée en tant qu'attribut

<input OnlyNumber="true" />

n'oubliez pas d'écrire votre directive dans le tableau de déclarations de votre module.

En utilisant regex, vous aurez toujours besoin de clés fonctionnelles

export class OnlyNumber {

  regexStr = '^[0-9]*$';
  constructor(private el: ElementRef) { }

  @Input() OnlyNumber: boolean;

  @HostListener('keydown', ['$event']) onKeyDown(event) {
    let e = <KeyboardEvent> event;
    if (this.OnlyNumber) {
        if ([46, 8, 9, 27, 13, 110, 190].indexOf(e.keyCode) !== -1 ||
        // Allow: Ctrl+A
        (e.keyCode == 65 && e.ctrlKey === true) ||
        // Allow: Ctrl+C
        (e.keyCode == 67 && e.ctrlKey === true) ||
        // Allow: Ctrl+V
        (e.keyCode == 86 && e.ctrlKey === true) ||
        // Allow: Ctrl+X
        (e.keyCode == 88 && e.ctrlKey === true) ||
        // Allow: home, end, left, right
        (e.keyCode >= 35 && e.keyCode <= 39)) {
          // let it happen, don't do anything
          return;
        }
      let ch = String.fromCharCode(e.keyCode);
      let regEx =  new RegExp(this.regexStr);    
      if(regEx.test(ch))
        return;
      else
         e.preventDefault();
      }
  }
}
88
omeralper

Si vous ne voulez pas de directive

https://stackblitz.com/edit/numeric-only

dans composant.html

<input (keypress)="numberOnly($event)" type="text">

dans composant.ts

export class AppComponent {

  numberOnly(event): boolean {
    const charCode = (event.which) ? event.which : event.keyCode;
    if (charCode > 31 && (charCode < 48 || charCode > 57)) {
      return false;
    }
    return true;

  }
}
45
rashidnk

Je voudrais développer la réponse donnée par @omeralper, qui, à mon avis, a fourni une bonne base pour une solution solide.

Ce que je propose est une version simplifiée et mise à jour avec les dernières normes Web. Il est important de noter que event.keycode est supprimé des normes Web et que les futures mises à jour du navigateur risquent de ne plus le prendre en charge. Voir https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode

En outre, la méthode

String.fromCharCode(e.keyCode);

ne garantit pas que le code de touche correspondant à la touche appuyée par l'utilisateur soit mappé sur la lettre attendue telle qu'identifiée sur le clavier de l'utilisateur, car des configurations de clavier différentes entraîneront des caractères différents pour un code de touche particulier. L'utilisation de cette fonctionnalité introduira des bogues difficiles à identifier et pouvant facilement casser les fonctionnalités de certains utilisateurs. Je propose plutôt l'utilisation de event.key, voir docs ici https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key

De plus, nous voulons seulement que la sortie résultante soit une décimale valide. Cela signifie que les nombres 1, 11.2, 5000.2341234 doivent être acceptés, mais que la valeur 1.1.2 ne doit pas être acceptée.

Notez que dans ma solution, les fonctionnalités de couper, copier et coller sont exclues car elles ouvrent des fenêtres pour détecter les bogues, en particulier lorsque des personnes collent du texte indésirable dans des champs associés. Cela nécessiterait un processus de nettoyage sur un gestionnaire de clés; ce qui n'est pas la portée de ce fil.

Voici la solution que je propose.

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

@Directive({
    selector: '[myNumberOnly]'
})
export class NumberOnlyDirective {
    // Allow decimal numbers. The \. is only allowed once to occur
    private regex: RegExp = new RegExp(/^[0-9]+(\.[0-9]*){0,1}$/g);

    // Allow key codes for special events. Reflect :
    // Backspace, tab, end, home
    private specialKeys: Array<string> = [ 'Backspace', 'Tab', 'End', 'Home' ];

    constructor(private el: ElementRef) {
    }

    @HostListener('keydown', [ '$event' ])
    onKeyDown(event: KeyboardEvent) {
        // Allow Backspace, tab, end, and home keys
        if (this.specialKeys.indexOf(event.key) !== -1) {
            return;
        }

        // Do not use event.keycode this is deprecated.
        // See: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode
        let current: string = this.el.nativeElement.value;
        // We need this because the current value on the DOM element
        // is not yet updated with the value from this event
        let next: string = current.concat(event.key);
        if (next && !String(next).match(this.regex)) {
            event.preventDefault();
        }
    }
}
26
JeanPaul A.

Je sais que la question est ancienne, mais comme il s’agit d’une fonction courante, je souhaite partager les modifications que j’ai apportées:

  • Séparateur décimal personnalisé (point ou virgule)
  • Prise en charge des nombres entiers uniquement ou des nombres entiers et décimaux
  • Prise en charge des nombres positifs uniquement ou des positifs et négatifs
  • Valider le signe moins (-) est au début
  • Prise en charge du collage de souris (avec certaines limitations toutefois https://caniuse.com/#feat=clipboard )
  • Prise en charge de la touche de commande Mac
  • Remplacez les chaînes telles que ".33" et "33." pour les versions correctes: 0.33 et 33.0

    import { Directive, ElementRef, HostListener, Input } from '@angular/core';
    
    @Directive({ selector: '[NumbersOnly]' })
    export class NumbersOnly { 
    
        @Input() allowDecimals: boolean = true;
        @Input() allowSign: boolean = false;
        @Input() decimalSeparator: string = '.';
    
        previousValue: string = '';
    
        // --------------------------------------
        //  Regular expressions
        integerUnsigned: string = '^[0-9]*$';
        integerSigned: string = '^-?[0-9]+$';
        decimalUnsigned: string = '^[0-9]+(.[0-9]+)?$';
        decimalSigned: string = '^-?[0-9]+(.[0-9]+)?$';
    
        /**
         * Class constructor
         * @param hostElement
         */
        constructor(private hostElement: ElementRef) { }
    
        /**
         * Event handler for Host's change event
         * @param e
         */
        @HostListener('change', ['$event']) onChange(e) {
    
                this.validateValue(this.hostElement.nativeElement.value);
    }
    
    /**
     * Event handler for Host's paste event
     * @param e
     */
    @HostListener('paste', ['$event']) onPaste(e) {
    
        // get and validate data from clipboard
        let value = e.clipboardData.getData('text/plain');
        this.validateValue(value);
        e.preventDefault();
    }
    
    /**
     * Event handler for Host's keydown event
     * @param event
     */
    @HostListener('keydown', ['$event']) onKeyDown(e: KeyboardEvent) {
    
        let cursorPosition: number = e.target['selectionStart'];
        let originalValue: string = e.target['value'];
        let key: string = this.getName(e);
        let controlOrCommand = (e.ctrlKey === true || e.metaKey === true);
        let signExists = originalValue.includes('-');
        let separatorExists = originalValue.includes(this.decimalSeparator);
    
        // allowed keys apart from numeric characters
        let allowedKeys = [
            'Backspace', 'ArrowLeft', 'ArrowRight', 'Escape', 'Tab'
        ];
    
        // when decimals are allowed, add
        // decimal separator to allowed codes when
        // its position is not close to the the sign (-. and .-)
        let separatorIsCloseToSign = (signExists && cursorPosition <= 1);
        if (this.allowDecimals && !separatorIsCloseToSign && !separatorExists) {
    
            if (this.decimalSeparator == '.')
                allowedKeys.Push('.');
            else
                allowedKeys.Push(',');
        }
    
        // when minus sign is allowed, add its
        // key to allowed key only when the
        // cursor is in the first position, and
        // first character is different from
        // decimal separator
        let firstCharacterIsSeparator = (originalValue.charAt(0) != this.decimalSeparator);
        if (this.allowSign && !signExists &&
            firstCharacterIsSeparator && cursorPosition == 0) {
    
            allowedKeys.Push('-');
        }
    
        // allow some non-numeric characters
        if (allowedKeys.indexOf(key) != -1 ||
            // Allow: Ctrl+A and Command+A
            (key == 'a' && controlOrCommand) ||
            // Allow: Ctrl+C and Command+C
            (key == 'c' && controlOrCommand) ||
            // Allow: Ctrl+V and Command+V
            (key == 'v' && controlOrCommand) ||
            // Allow: Ctrl+X and Command+X
            (key == 'x' && controlOrCommand)) {
            // let it happen, don't do anything
            return;
        }
    
        // save value before keydown event
        this.previousValue = originalValue;
    
        // allow number characters only
        let isNumber = (new RegExp(this.integerUnsigned)).test(key);
        if (isNumber) return; else e.preventDefault();
    }
    
    /**
     * Test whether value is a valid number or not
     * @param value
     */
    validateValue(value: string): void {
    
        // choose the appropiate regular expression
        let regex: string;
        if (!this.allowDecimals && !this.allowSign) regex = this.integerUnsigned;
        if (!this.allowDecimals && this.allowSign) regex = this.integerSigned;
        if (this.allowDecimals && !this.allowSign) regex = this.decimalUnsigned;
        if (this.allowDecimals &&  this.allowSign) regex = this.decimalSigned;
    
        // when a numbers begins with a decimal separator,
        // fix it adding a zero in the beginning
        let firstCharacter = value.charAt(0);
        if (firstCharacter == this.decimalSeparator)
            value = 0 + value;
    
        // when a numbers ends with a decimal separator,
        // fix it adding a zero in the end
        let lastCharacter = value.charAt(value.length-1);
        if (lastCharacter == this.decimalSeparator)
            value = value + 0;
    
        // test number with regular expression, when
        // number is invalid, replace it with a zero
        let valid: boolean = (new RegExp(regex)).test(value);
        this.hostElement.nativeElement['value'] = valid ? value : 0;
    }
    
    /**
     * Get key's name
     * @param e
     */
    getName(e): string {
    
        if (e.key) {
    
            return e.key;
    
        } else {
    
            // for old browsers
            if (e.keyCode && String.fromCharCode) {
    
                switch (e.keyCode) {
                    case   8: return 'Backspace';
                    case   9: return 'Tab';
                    case  27: return 'Escape';
                    case  37: return 'ArrowLeft';
                    case  39: return 'ArrowRight';
                    case 188: return ',';
                    case 190: return '.';
                    case 109: return '-'; // minus in numbpad
                    case 173: return '-'; // minus in alphabet keyboard in firefox
                    case 189: return '-'; // minus in alphabet keyboard in chrome
                    default: return String.fromCharCode(e.keyCode);
                }
            }
        }
    }
    

Usage:

 <input NumbersOnly
        [allowDecimals]="true"
        [allowSign]="true"
        type="text">
20
Elvis Fernandez
<input type="text" (keypress)="keyPress($event)">


  keyPress(event: any) {
    const pattern = /[0-9\+\-\ ]/;

    let inputChar = String.fromCharCode(event.charCode);
    if (event.keyCode != 8 && !pattern.test(inputChar)) {
      event.preventDefault();
    }
  }
13
ketan pradhan

Une solution plus concise. Essayez cette directive.

Peut aussi être utilisé si vous utilisez ReactiveForms.

export class NumberOnlyDirective {
  private el: NgControl;

  constructor(private ngControl: NgControl) {
    this.el = ngControl;
  }

  // Listen for the input event to also handle copy and paste.
  @HostListener('input', ['$event.target.value'])
  onInput(value: string) {
    // Use NgControl patchValue to prevent the issue on validation
    this.el.control.patchValue(value.replace(/[^0-9]/g, ''));
  }
}

Utilisez-le sur vos entrées comme ceci:

<input matInput formControlName="aNumberField" numberOnly>
10
Ben Gulapa

Vous devez utiliser type = "nombre" à la place du texte. Vous pouvez également spécifier des nombres maximum et minimum

<input type="number" name="quantity" min="1" max="5">
8
Zia Khan

vous pouvez y arriver comme ça

<input type="text" pInputText (keypress)="onlyNumberKey($event)" maxlength="3"> 

onlyNumberKey(event) {
    return (event.charCode == 8 || event.charCode == 0) ? null : event.charCode >= 48 && event.charCode <= 57;
}

//for Decimal you can use this as

onlyDecimalNumberKey(event) {
    let charCode = (event.which) ? event.which : event.keyCode;
    if (charCode != 46 && charCode > 31
        && (charCode < 48 || charCode > 57))
        return false;
    return true;
}

j'espère que cela vous aidera.

8
Pardeep Jain

Utilisez l'attribut pattern pour la saisie, comme ci-dessous:

<input type="text" pattern="[0-9]+" >
5
Behnam Azimi

Pour ce faire, j'ai lié une fonction à la méthode onInput comme ceci:

(input)="stripText(infoForm.get('uin'))

Voici l'exemple dans ma fiche:

<form [formGroup]="infoForm" (submit)="next()" class="ui form">
    <input type="text" formControlName="uin" name="uin" id="uin" (input)="stripText(infoForm.get('uin'))" required/>
</form>

Ensuite, j'ai ajouté la fonction suivante à mon composant:

  stripText(control: FormControl) {
   control.setValue(control.value.replace(/[^0-9]/g, ''));
  }

Cette expression rationnelle /[^0-9]/g recherche tout ce qui n’est pas un nombre et utilise .replace je l’ai définie pour ne rien remplacer. Ainsi, lorsqu'un utilisateur essaie de saisir un caractère qui n'est pas un nombre (dans ce cas, un caractère différent de zéro à neuf), il semble que rien ne se passe dans la zone de texte.

4
Christopher

Vous pouvez utiliser regex:

<input type="text" (keypress)="numericOnly($event)">

numericOnly(event): boolean {    
    let patt = /^([0-9])$/;
    let result = patt.test(event.key);
    return result;
}
4
Aathreya

Merci à JeanPaul A. et à rdanielmurphy. J'avais créé ma propre directive personnalisée pour limiter le champ de saisie au nombre uniquement. Également ajouté les attributs d'entrée max et min. Travaillera dans angular 7 également.

angulaire

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

@Directive({
  selector: '[appNumberOnly]'
})
export class NumberOnlyDirective {
  // Allow decimal numbers. The \. is only allowed once to occur
  private regex: RegExp = new RegExp(/^[0-9]+(\.[0-9]*){0,1}$/g);

  // Allow key codes for special events. Reflect :
  // Backspace, tab, end, home
  private specialKeys: Array<string> = ['Backspace', 'Tab', 'End', 'Home'];
  constructor(private el: ElementRef) { }

  @Input() maxlength: number;
  @Input() min: number;
  @Input() max: number;

  @HostListener('keydown', ['$event'])
  onKeyDown(event: KeyboardEvent) {
    // Allow Backspace, tab, end, and home keys
    if (this.specialKeys.indexOf(event.key) !== -1) {
      return;
    }

    // Do not use event.keycode this is deprecated.
    // See: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode
    const current: string = this.el.nativeElement.value;

    // We need this because the current value on the DOM element
    // is not yet updated with the value from this event
    const next: string = current.concat(event.key);
    if (next && !String(next).match(this.regex) || (this.maxlength && next.length > this.maxlength) ||
      (this.min && +next < this.min) ||
      (this.max && +next >= this.max)) {
      event.preventDefault();
    }
  }

  @HostListener('paste', ['$event']) onPaste(event) {
    // Don't allow pasted text that contains non-numerics
    const pastedText = (event.originalEvent || event).clipboardData.getData('text/plain');

    if (pastedText) {
      const regEx = new RegExp('^[0-9]*$');
      if (!regEx.test(pastedText) || (this.maxlength && pastedText.length > this.maxlength) ||
        (this.min && +pastedText < this.min) ||
        (this.max && +pastedText >= this.max)) {
        event.preventDefault();
      }
    }
  }

}

HTML

<input type="text" class="text-area" [(ngModel)]="itemName" maxlength="3" appNumberOnly />
3
leox

Modèle pour le modèle de numéro de téléphone valide ('^ ((\ + 91 -?) | 0)? [0-9] {10} $')

Modèle permettant d’accepter uniquement les chiffres du modèle de zone de texte ('[0-9] *')

patter pour accepter uniquement le numéro avec un numéro spécifique, par exemple: code PIN. motif ('^ [0-9] {5} $')

3
Satish Deokar

J'ai apporté quelques modifications à la directive ci-dessus et implémenté min, max, maxlength.

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

@Directive({
  selector: '[numberOnly]'
})
export class NumbersOnlyDirective {

  private regex: RegExp = new RegExp(/[0-9]/g);
  // Allow key codes for special events. Reflect :
  private specialKeys: Array<number> = [46, 8, 9, 27, 13, 110, 190, 35, 36, 37, 39];
  // Backspace, tab, end, home

  @Input() maxlength: number;
  @Input() min: number;
  @Input() max: number;

  constructor(private el: ElementRef) {
  }
    @HostListener('keydown', ['$event'])
    onKeyDown(event: KeyboardEvent) {
    e = <KeyboardEvent>event;

if ((
  (this.specialKeys.indexOf(event.which) > -1) ||
  // to allow backspace, enter, escape, arrows  
  (e.which == 65 && e.ctrlKey == true) ||
  // Allow: Ctrl+C        
  (e.which == 67 && e.ctrlKey == true) ||
  // Allow: Ctrl+X
  (e.which == 88 && e.ctrlKey == true))) {
  return;
} else if (// to allow numbers  
  (e.which >= 48 && e.which <= 57) ||
  // to allow numpad number  
  (event.which >= 96 && event.which <= 105)) { }
else {
      event.preventDefault();
    }
    let current: string = this.el.nativeElement.value;

    let next: string = current.concat(event.key);
    if ((next && !String(next).match(this.regex)) ||
      (this.maxlength && next.length > this.maxlength) ||
      (this.min && +next < this.min) ||
      (this.max && +next >= this.max)) {
      event.preventDefault();
    }

  }
}
2
Karan Mistry

Créez simplement une directive et ajoutez ci-dessous hostlistener:

@HostListener('input', ['$event'])
    onInput(event: Event) {
        this.elementRef.nativeElement.value = (<HTMLInputElement>event.currentTarget).value.replace(/[^0-9]/g, '');
    }

Remplacer le texte invalide par vide. Toutes les clés et combinaisons de touches fonctionnent désormais sur tous les navigateurs jusqu'à IE9.

2
Gaurav Joshi

Avec le support pour la désinfection du contenu collé:

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

@Directive({
  selector: '[NumbersOnly]'
})
export class NumbersOnlyDirective {

    DIGITS_REGEXP =  new RegExp(/\D/g);
    constructor(private el: ElementRef) { 

        // Sanatize clipboard by removing any non-numeric input after pasting
        this.el.nativeElement.onpaste = (e:any) => {
            e.preventDefault();
            let text;
            let clp = (e.originalEvent || e).clipboardData;
            if (clp === undefined || clp === null) {
                text = (<any>window).clipboardData.getData('text') || '';
                if (text !== '') {
                    text = text.replace(this.DIGITS_REGEXP, '');
                    if (window.getSelection) {
                        let newNode = document.createElement('span');
                        newNode.innerHTML = text;
                        window.getSelection().getRangeAt(0).insertNode(newNode);
                    } else {
                        (<any>window).selection.createRange().pasteHTML(text);
                    }
                }
            } else {
                text = clp.getData('text/plain') || '';
                if (text !== '') {
                    text = text.replace(this.DIGITS_REGEXP, '');
                    document.execCommand('insertText', false, text);
                }
            }
        };
    }

  @HostListener('keydown', ['$event']) onKeyDown(event) {
    let e = <KeyboardEvent> event;
    if ([46, 8, 9, 27, 13, 110, 190].indexOf(e.keyCode) !== -1 ||
      // Allow: Ctrl+A
      (e.keyCode === 65 && (e.ctrlKey || e.metaKey)) ||
      // Allow: Ctrl+C
      (e.keyCode === 67 && (e.ctrlKey || e.metaKey)) ||
      // Allow: Ctrl+V
      (e.keyCode === 86 && (e.ctrlKey || e.metaKey)) ||
      // Allow: Ctrl+X
      (e.keyCode === 88 && (e.ctrlKey || e.metaKey)) ||
      // Allow: home, end, left, right
      (e.keyCode >= 35 && e.keyCode <= 39)) {
        // let it happen, don't do anything
        return;
      }
      // Ensure that it is a number and stop the keypress
      if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
          e.preventDefault();
      }
    }

}
1
mad_fox

de la réponse de @omeralper. Je change un peu qui n'acceptera pas les règles ascii (code 110,190). et utilisez let ch = (e.key); pour comparer avec une expression régulière lorsque vous changez de langue (comme le thaï ou le japonais), il n'acceptera pas le caractère de ces langues

export class OnlyNumber {

  regexStr = '^[0-9]*$';
  constructor(private el: ElementRef) { }

  @Input() OnlyNumber: boolean;

  @HostListener('keydown', ['$event']) onKeyDown(event) {
    let e = <KeyboardEvent> event;
    if (this.OnlyNumber) {
      // console.log(event, this.OnlyNumber);
        if ([46, 8, 9, 27, 13].indexOf(e.keyCode) !== -1) {
          return;
        }
      let ch = (e.key);
      let regEx =  new RegExp(this.regexStr);   
      if(regEx.test(ch))
        return;
      else
         e.preventDefault();
    }
  }
}

espérons que cette aide :)

1
Supakorn Thongtra

Vous pouvez créer ce validateur et l'importer dans votre composant.
Valide fondamentalement la chaîne de saisie du formulaire:

  • vérifier qu'il n'y a pas de point
  • convertit une chaîne en nombre
  • check est un entier
  • chèque est supérieur à zéro

Pour l'implémenter dans votre projet:

  1. chemin suggéré dans votre dossier d'application: src/app/validators/number.validator.ts
  2. importer dans votre composant

    import { NumberValidator } from '../../validators/number.validator';

  3. l'ajouter au contrôle de formulaire
    inputNumber: ['', [NumberValidator.isInteger]],
  4. si vous ne voulez pas afficher le caractère non valide, liez un (change)="deleteCharIfInvalid()" à l'entrée, si form.get('inputNumber').hasError('isInteger') est true, supprimez le dernier caractère inséré.
// FILE: src/app/validators/number.validator.ts

import { FormControl } from '@angular/forms';

export interface ValidationResult {
    [key: string]: boolean;
}

export class NumberValidator {

    public static isInteger(control: FormControl): ValidationResult {
        // check if string has a dot
        let hasDot:boolean = control.value.indexOf('.') >= 0 ? true : false;
        // convert string to number
        let number:number = Math.floor(control.value);
        // get result of isInteger()
        let integer:boolean = Number.isInteger(number);
        // validate conditions 
        let valid:boolean = !hasDot && integer && number>0;
        console.log('isInteger > valid', hasDot, number, valid);
        if (!valid) {
            return { isInteger: true };
        }
        return null;
    }        
}
1
guillefd

En voici une simple: directive simple sur l'événement keydown, elle vérifie que la longueur d'une clé est égale à une et que la clé n'est pas un nombre à preventDefault() et elle ne rend pas ce caractère.

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

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

}

HTML:

<input type="text" [(ngModel)]="numModel" numbersOnly />

Limitations: Cela permettra de coller en utilisant une souris de cette façon acceptera les autres caractères. Pour éviter cela, vous pouvez transmettre le modèle en entrée à la directive et à ngOnChage à cette valeur de modification de modèle en chiffres uniquement:

Comme ci-dessous:

EDIT: Code ajouté pour détecter les changements dans le modèle et mettre à jour la valeur de l'entrée

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

@Directive({
    selector: '[numbersOnly]'
})
export class NumbersOnlyDirective implements OnChanges {

    @Input() numbersOnly: any;

    constructor(private el: ElementRef) {}

    @HostListener('keydown', ['$event'])
    keyDownEvent(event: KeyboardEvent) {
        // Add other conditions if need to allow ctr+c || ctr+v
        if (event.key.length === 1 && (event.which < 48 || event.which > 57)) {
            event.preventDefault();
        }
    }

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

}

HTML:

<input type="text" [(ngModel)]="numModel" [numbersOnly]="numModel" />
1
Lahar Shah

Ne serait pas assez simple pour écrire

onlyNumbers(event) {
if(isNaN(event.target.value * 1)) {
 console.log("Not a number")
} else {
  console.log("Number")
}

}

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


    //only-digits
    @Directive({
      selector: '[only-digits]'
    })
    export class OnlyDigits {

      constructor(public el: ElementRef) {

        this.el.nativeElement.onkeypress = (evt) => {
          if (evt.which < 48 || evt.which > 57) {
            evt.preventDefault();
          }
        };

      }
    }

La directive est aussi un meilleur moyen de le faire

0
user8199162

J'ai vu beaucoup de commentaires sur la gestion du copier/coller.

Pour tirer parti de la réponse @omeralper, vous pouvez ajouter un gestionnaire d’événement coller à la directive onlyNumber afin de gérer le copier/coller:

 @HostListener('paste', ['$event']) onPaste(event) {
  // Don't allow pasted text that contains non-numerics
  var pastedText = (event.originalEvent || event).clipboardData.getData('text/plain');

  if (pastedText) {
    var regEx = new RegExp('^[0-9]*$');
    if (!regEx.test(pastedText)) {
      event.preventDefault();
    }
}

Cela permettra uniquement au contenu d'être copié et collé dans la zone de texte UNIQUEMENT s'il s'agit d'un numéro. C'est la solution la plus simple. Changer le contenu du presse-papier pour supprimer les éléments non numériques est beaucoup plus compliqué et pourrait ne pas en valoir la peine.

Pour obtenir du texte collé de IE, vous pouvez utiliser les éléments suivants:

window.clipboardData.getData('Text');
0
rdanielmurphy

fromCharCode renvoie 'a' lorsque vous appuyez sur le pavé numérique '1', cette méthode doit donc être évitée

(admin: impossible de commenter comme d'habitude)

0
fdsfdsfdsfds

Si vous utilisez primeng et Angular 6 ou une version ultérieure, il existe le composant p-inputMask. Il empêche le typage alpha ET les valeurs négatives https://www.primefaces.org/primeng/#/inputmask

0
dotista2008

Pourquoi ne pas utiliser ControlValueAccessor?

https://stackblitz.com/edit/angular-wwo9kt

Vous pouvez écouter l'événement 'input' et il n'est pas nécessaire de vérifier les codes clés. Avec ControlValueAccessor, vous pouvez vous assurer que le modèle est mis à jour correctement.

export class OnlyNumberDirective implements ControlValueAccessor {

private onChange: (val: string) => void;
private onTouched: () => void;

constructor(
    private elementRef: ElementRef,
    private renderer: Renderer2
) {
}

@HostListener('input', ['$event'])
onInputChange() {
    this.updateTextInput(this.elementRef.nativeElement.value);
}

private updateTextInput(value) {
    const filteredValue = value.replace(/[^0-9]*/g, '');
    this.renderer.setProperty(this.elementRef.nativeElement, 'value', filteredValue);
    this.onChange(filteredValue);
}

// ControlValueAccessor Interface
registerOnChange(fn: any): void {
    this.onChange = fn;
}

writeValue(value: string): void {
    if (value) {
        this.updateTextInput(value);
    }
}
}
0
spierala

Utilisez simplement le numéro de type sur votre texte comme ci-dessous:

<input type="number" class="form-control" matInput name="value" placeholder="xxx" (change)="xxx()" formControlName="value">
0
Abdus Salam Azad

Ci-dessous, mon code angular qui permet au seul nombre d'entrer et de ne coller que le nombre, pas le texte.

<input id="pId" maxlength="8" minlength="8" type="text" [(ngModel)]="no" formControlName="prefmeno" name="no" class="form-control">

Et dans le fichier ts ajouté dans ngOnIt.

ngOnInit() {
  setTimeout(() => {
  jQuery('#pId').on('paste keyup', function(e){
    jQuery(this).val(document.getElementById('pId').value.replace(/[^\d]/g, ''));
  });
}, 2000);
}

J'ai utilisé setTimeout pour le temps d'attente pour charger DOM. Et jquery utilisé avec javascript pour effectuer cette tâche. 'Coller' et 'keyup' sont utilisés pour déclencher coller et entrer dans le champ.

0
ajay hariyal