web-dev-qa-db-fra.com

angular valider le type d'entrée = "nombre"

J'ai un balisage comme celui-ci:

<form name="myForm" ng-controller="myCtrl" novalidate>
    <input ng-model="theValue" type="range" min="0" max="100" required>
    <input ng-model="theValue" type="number" required></input>
    <span ng-show="theValue.$error.number">Hey! No letters, buddy!</span>
</form>

Et je veux que la durée s'affiche lorsque l'utilisateur tape accidentellement une lettre dans la deuxième entrée. C'est simple, non? En tant que problème (probablement) lié, la valeur de la deuxième entrée disparaît lorsque l'utilisateur déplace la première entrée du curseur. Pourquoi? Cela ne se produit pas si je supprime type-number à partir du balisage.

Pour être clair: je veux que l'utilisateur voit l'erreur d'info-bulle immédiatement lorsqu'il est tapé, sans aucune action "soumettre". (Je préfère ne pas avoir à utiliser l'élément form du tout, mais toutes les démos associées semblent l'exiger.)

http://jsfiddle.net/7FfWT/

Toute solution de contournement est la bienvenue. Veuillez poster un violon de travail si possible.

18
Ben

Il semble y avoir un problème étrange avec type="number" jouer bien avec d'autres inputs.

Les messages de ce message sur les groupes Google devraient vous mettre sur la bonne voie. En particulier, le dernier message là-bas: https://groups.google.com/forum/#!msg/angular/Ecjx2fo8Qvk/x6iNlZrO_mwJ

Le lien jsfiddle est: http://jsfiddle.net/ABE8U/

En guise de solution, il a fait une directive:

.directive('toNumber', function () {
    return {
        require: 'ngModel',
        link: function (scope, elem, attrs, ctrl) {
            ctrl.$parsers.Push(function (value) {
                return parseFloat(value || '');
            });
        }
    };
});

Crédit à Schmuli Raskin

16
jzm

Vous pouvez également utiliser ng-pattern comme validateur:

<input type="number" ng-model="theValue" name="theValue" step="1" min="0" max="10"  ng-pattern="integerval" required>
<span ng-show="form.theValue.$invalid">Hey! No letters, buddy!</span>

$scope.integerval = /^\d*$/;
15
zenio

J'ai mis à jour la directive pour qu'elle fonctionne avec les filtres ng-repeat. Remarquez le "$", qui est un caractère générique. Cette directive devrait gérer 0 très bien. Il bascule vers le caractère générique sur

.directive('toNumber', function() {
    return {
        require: 'ngModel',
        link: function(scope, elem, attrs, ctrl) {
            ctrl.$parsers.Push(function(value) {
                return value===0 ? 0 : (parseFloat(value) || '$');
            });
    };
})
1
FesterCluck

jzm, la réponse de s est vraiment un truc merveilleux et m'a fait gagner du temps.

Je vais juste plus loin et je remplace parseFloat(value) par ce qu'il fait réellement.

directive('number', function () {
    return {
        require: 'ngModel',
        link: function (scope, elem, attrs, ngModel) {

            ngModel.$parsers.Push(function (value) {
                if (value==null)
                  return NaN;
            });
        }
    };
});
0
immirza

la réponse de jzm a fonctionné pour moi jusqu'à ce que j'aie besoin de "0" comme entrée. J'ai ajusté le code de jzm:

.directive('toNumber', function () {
    return {
        require: 'ngModel',
        link: function (scope, elem, attrs, ctrl) {
            ctrl.$parsers.Push(function (value) {
                if (value === 0)
                    return 0;

                return parseFloat(value || '');
            });
        }
    };
});

Remarquez l'ajout du bloc if (value === 0).

Quelqu'un qui comprend mieux les comparaisons logiques JavaScript que moi pourrait probablement créer un code plus élégant.

0
Jeremy