Dans Angular 2, comment puis-je masquer un champ de saisie (zone de texte) de sorte qu'il n'accepte que des chiffres et non des caractères alphabétiques?
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 afficher l'année.
En utilisant Angular 2, 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 n'accepte que des nombres?
Quelles sont les différentes manières d'y parvenir?
Remarque: je dois y parvenir en utilisant uniquement une zone de texte et sans utiliser le type de numéro d'entrée.
html
angular
input
angularjs-directive
Aniruddha Pondhe
la source
la source
Réponses:
Vous pouvez utiliser des 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 des déclarations de votre module.
En utilisant regex, vous auriez 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(); } } }
la source
(e.keyCode == 86 && e.ctrlKey === true)
aux conditions, la copie fonctionne mais la pâte ne fonctionnait pase.keyCode == 109 || e.keyCode ==190
pour.
et-
mais-
n'est pas accepté?Si vous ne voulez pas de directive
https://stackblitz.com/edit/numeric-only
dans component.html
<input (keypress)="numberOnly($event)" type="text">
dans component.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; } }
la source
Je sais que c'est une vieille question, mais comme il s'agit d'une fonctionnalité commune, je souhaite partager les modifications que j'ai apportées:
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">
la source
Je voudrais m'appuyer sur la réponse de @omeralper, qui à mon avis a fourni une bonne base pour une solution solide.
Ce que je propose, c'est une version simplifiée et à jour avec les derniers standards du web. Il est important de noter que event.keycode est supprimé des normes Web et que les futures mises à jour du navigateur pourraient ne plus le prendre en charge. Voir https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode
De plus, la méthode
String.fromCharCode(e.keyCode);
ne garantit pas que le keyCode se rapportant à la touche enfoncée par l'utilisateur correspond à la lettre attendue comme identifiée sur le clavier de l'utilisateur, car différentes configurations de clavier entraîneront un code de touche particulier de caractères différents. Son utilisation introduira des bogues difficiles à identifier et peut facilement interrompre la fonctionnalité pour certains utilisateurs. Je propose plutôt l'utilisation de event.key, voir la documentation 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, j'exclus la fonctionnalité couper, copier et coller car elle ouvre les fenêtres pour les bogues, en particulier lorsque les gens collent du texte indésirable dans les champs associés. Cela nécessiterait un processus de nettoyage sur un gestionnaire de keyup; 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(); } } }
la source
Une solution plus concise. Essayez cette directive.
Peut également ê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>
la source
<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(); } }
la source
Vous devez utiliser type = "number" à la place du texte. Vous pouvez également spécifier des nombres maximum et minimum
<input type="number" name="quantity" min="1" max="5">
la source
type="number"
est qu'il accepte le caractèree
dans le cadre de la notation scientifiquetu peux l'atteindre 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.
la source
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; }
la source
Utilisez l'
pattern
attribut pour l'entrée comme ci-dessous:<input type="text" pattern="[0-9]+" >
la source
Je sais que cela a beaucoup de réponses, mais je devais gérer les éléments suivants (qu'aucune des réponses ne semblait pleinement soutenir):
La solution me permet de définir une zone de texte comme celle-ci:
<textarea class="form-control" [(ngModel)]="this.myModelVariable" appOnlyNumbers [allowNegative]="true" [allowMultiLine]="true" [allowDecimal]="true" [maxLength]="10" placeholder="Enter values (one per line)"></textarea>
Ou si je veux juste des entiers positifs
<textarea class="form-control" [(ngModel)]="this.myModelVariable" appOnlyNumbers [allowMultiLine]="true" [maxLength]="9" placeholder="Enter values (one per line)"></textarea>
Voici ma directive:
import { Directive, HostListener, Input, ElementRef } from '@angular/core'; @Directive({ selector: '[appOnlyNumbers]' }) export class OnlyNumbersDirective { constructor(private el: ElementRef) { } @Input() allowMultiLine: boolean = false; @Input() allowNegative: boolean = false; @Input() allowDecimal: boolean = false; @Input() maxLength: number = 0; regex: RegExp; @HostListener('keypress', ['$event']) onKeyPress(event: KeyboardEvent) { this.validate(event, event.key === 'Enter' ? '\n' : event.key); } @HostListener('paste', ['$event']) onPaste(event: Event) { const pastedText = (<any>window).clipboardData && (<any>window).clipboardData.getData('Text') // If IE, use window || <ClipboardEvent>event && (<ClipboardEvent>event).clipboardData.getData('text/plain'); // Non-IE browsers this.validate(event, pastedText); } @HostListener('cut', ['$event']) onCut(event: Event) { this.validate(event, ''); } validate(event: Event, text: string) { const txtInput = this.el.nativeElement; const newValue = (txtInput.value.substring(0, txtInput.selectionStart) + text + txtInput.value.substring(txtInput.selectionEnd)); if (!this.regex) { this.regex = <RegExp>eval('/^' + (this.allowNegative ? '-?' : '') + (this.allowDecimal ? '((\\d+\\.?)|(\\.?))\\d*' : '\\d*') + '$/g'); } var lines = this.allowMultiLine ? newValue.split('\n') : [newValue]; for (let line of lines) { let lineText = line.replace('\r', ''); if (this.maxLength && lineText.length > this.maxLength || !lineText.match(this.regex)) { event.preventDefault(); return; } } } }
la source
Pour ce faire, j'ai lié une fonction à la méthode onInput comme ceci:
(input)="stripText(infoForm.get('uin'))
Voici l'exemple dans mon formulaire:
<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 régulière
/[^0-9]/g
recherche tout ce qui n'est pas un nombre et en utilisant.replace
je l'ai défini pour qu'il soit remplacé par rien. Ainsi, lorsqu'un utilisateur tente de saisir un caractère qui n'est pas un nombre (dans ce cas, un caractère qui n'est pas de zéro à neuf), il semble que rien ne se passe dans la zone de texte.la source
Eh bien merci à JeanPaul A. et rdanielmurphy. J'avais créé ma propre directive personnalisée pour limiter le champ de saisie au nombre uniquement. Ajout des attributs d'entrée max et min. Fonctionnera également en angulaire 7.
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 />
la source
Une approche moderne pour la meilleure réponse (sans e.keyCode obsolète):
@HostListener('keydown', ['$event']) onKeyDown(event) { let e = <KeyboardEvent> event; if (['Delete', 'Backspace', 'Tab', 'Escape', 'Enter', 'NumLock', 'ArrowLeft', 'ArrowRight', 'End', 'Home', '.'].indexOf(e.key) !== -1 || // Allow: Ctrl+A (e.key === 'a' && (e.ctrlKey || e.metaKey)) || // Allow: Ctrl+C (e.key === 'c' && (e.ctrlKey || e.metaKey)) || // Allow: Ctrl+V (e.key === 'v' && (e.ctrlKey || e.metaKey)) || // Allow: Ctrl+X (e.key === 'x' && (e.ctrlKey || e.metaKey))) { // let it happen, don't do anything return; } // Ensure that it is a number and stop the keypress if ((e.shiftKey || ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'].indexOf(e.key) === -1)) { e.preventDefault(); } }
la source
Directive RegExp arbitraire
Voici une petite directive qui utilise une expression rationnelle arbitraire et bloque l'utilisateur pour taper une valeur invalide
Afficher l'extrait de code
import {Directive, HostListener, Input} from '@angular/core'; @Directive({selector: '[allowedRegExp]'}) export class AllowedRegExpDirective { @Input() allowedRegExp: string; @HostListener('keydown', ['$event']) onKeyDown(event: any) { // case: selected text (by mouse) - replace it let s= event.target.selectionStart; let e= event.target.selectionEnd; let k= event.target.value + event.key; if(s!=e) { k= event.target.value k= k.slice(0,s) + event.key + k.slice(e,k.length); } // case: special characters (ignore) if(['ArrowLeft','ArrowRight','ArrowUp','ArroDown','Backspace','Tab','Alt' 'Shift','Control','Enter','Delete','Meta'].includes(event.key)) return; // case: normal situation - chceck regexp let re = new RegExp(this.allowedRegExp); if(!re.test(k)) event.preventDefault(); } }
Pour masquer uniquement les nombres, utilisez
<input [allowedRegExp]="'^[0-9]*$'" type="text" ... >
la source
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, ''); }
Remplacez le texte non valide par un texte vide. Toutes les touches et combinaisons de touches fonctionneront désormais sur tous les navigateurs jusqu'à IE9.
la source
Modèle pour le modèle de numéro de mobile valide ('^ ((\ + 91 -?) | 0)? [0-9] {10} $')
Modèle pour accepter uniquement le nombre du modèle de zone de texte ('[0-9] *')
patter pour accepter uniquement un nombre avec un numéro spécifique, par exemple: Pincode. motif ('^ [0-9] {5} $')
la source
J'ai apporté quelques modifications à la directive ci-dessus et mis en œuvre 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(); } } }
la source
de la réponse de @omeralper. Je change un peu qui n'accepte pas la période ascii (code clé 110,190). et utilisez let ch = (e.key); pour comparer avec l'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 cette aide :)
la source
Vous pouvez créer ce validateur et l'importer dans votre composant.
Valide essentiellement la chaîne d'entrée du formulaire:
Pour l'implémenter dans votre projet:
importer dans votre composant
import { NumberValidator } from '../../validators/number.validator';
inputNumber: ['', [NumberValidator.isInteger]],
(change)="deleteCharIfInvalid()"
à l'entrée, siform.get('inputNumber').hasError('isInteger')
c'est le castrue
, 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; } }
la source
Number.isInteger(Math.floor(control.value))
sera pas toujours vrai? Je pense que ça devrait l'être à laparseFloat
place.Avec prise en charge de 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(); } } }
la source
En voici une simple: Directive simple Lors de l'événement keydown, il vérifie que la longueur d'une clé est un et que la clé n'est pas un nombre à
preventDefault()
et il ne rendra 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 à l'aide d'une souris de cette façon acceptera d'autres caractères. Pour éviter cela, vous pouvez passer le modèle en entrée de la directive et
ngOnChage
à ce modèle, modifiez la valeur uniquement en nombres:Comme ci-dessous:
EDIT: Ajout du code 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" />
la source
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 également le meilleur moyen de le faire
la source
<input oninput="this.value=this.value.replace(/[^0-9]/g,'')"
ou: 2. dans le fichier HTML:
<input [(ngModel)]="data" (keypress)="stripText($event)" class="form-control">
dans le fichier ts:
stripText(event) { const seperator = '^([0-9])'; const maskSeperator = new RegExp(seperator , 'g'); let result =maskSeperator.test(event.key); return result; }
Cette solution 2 fonctionne
la source
fromCharCode renvoie 'a' en appuyant sur le pavé numérique '1' donc ce méthoïde doit être évité
(administrateur: n'a pas pu commenter comme d'habitude)
la source
J'ai vu beaucoup de commentaires sur la gestion du copier / coller.
Pour récupérer la réponse @omeralper, vous pouvez ajouter un gestionnaire d'événements de collage à la directive onlyNumber pour 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 nombre. C'est la solution la plus simple. Changer le contenu du presse-papiers 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é à partir d'IE, vous pouvez utiliser ce qui suit:
window.clipboardData.getData('Text');
la source
Si vous utilisez primeng et Angular 6 ou supérieur, il existe le composant p-inputMask. Il empêche le typage alpha ET les valeurs négatives https://www.primefaces.org/primeng/#/inputmask
la source
Ne serait pas assez simple pour écrire
onlyNumbers(event) { if(isNaN(event.target.value * 1)) { console.log("Not a number") } else { console.log("Number") }
}
la source
Vous pouvez également créer une directive qui implémente l'interface ControlValueAccessor ( https://angular.io/api/forms/ControlValueAccessor ).
Voir l'exemple de travail ici: https://stackblitz.com/edit/angular-input-field-to-accept-only-numbers
Vous pouvez écouter l'événement 'input' et il n'est pas nécessaire de vérifier les codes clés. Il prend en charge le copier-coller et s'intègre parfaitement à l'API Angular Forms grâce à l'interface ControlValueAccessor.
Directif:
@Directive({ ... selector: '[onlyNumber]' }) export class OnlyNumberDirective implements ControlValueAccessor { private onChange: (val: string) => void; ... private value: string; constructor( private elementRef: ElementRef, private renderer: Renderer2 ) { } ... @HostListener('input', ['$event.target.value']) onInputChange(value: string) { const filteredValue: string = filterValue(value); this.updateTextInput(filteredValue, this.value !== filteredValue); } private updateTextInput(value, propagateChange) { this.renderer.setProperty(this.elementRef.nativeElement, 'value', value); if (propagateChange) { this.onChange(value); } this.value = value; } // ControlValueAccessor Interface ... registerOnChange(fn: any): void { this.onChange = fn; } writeValue(value: string): void { value = value ? String(value) : ''; this.updateTextInput(value, false); } } function filterValue(value): string { return value.replace(/[^0-9]*/g, ''); }
Usage:
<input name="number" type="text" onlyNumber [(ngModel)]="someNumber">
la source
Casting car il fonctionne également avec un 0 de tête comme 00345
@Directive({ selector: '[appOnlyDigits]' }) export class AppOnlyDigitsDirective { @HostListener('input', ['$event']) onKeyDown(ev: KeyboardEvent) { const input = ev.target as HTMLInputElement; input.value = String(input.value.replace(/\D+/g, '')); } }
la source