web-dev-qa-db-fra.com

Angularjs Dynamic ng-pattern validation

J'ai un formulaire qui si une case à cocher est false applique la validation sur une entrée de texte en utilisant la directive ng-required. Si la case à cocher est true, le champ est masqué et le paramètre ng-required est défini sur false.

Le problème est que j’ai aussi une expression rationnelle à valider spécifiée sur l’entrée en utilisant également la directive angg-pattern. Le problème que je rencontre est que si un utilisateur remplit un numéro de téléphone invalide, coche la case pour désactiver cette entrée (et ne nécessite par conséquent aucune validation supplémentaire), le formulaire n'autorisera pas la soumission car il est invalide sur la base du modèle ng.

J'ai tenté de résoudre ce problème en ajoutant une fonction ng-change pour définir le modèle d'entrée sur null. Toutefois, le motif ng et le champ sont donc toujours définis sur non valides dans le jeu initial de la case à cocher sur false. Si toutefois je décoche la case, remettant tout en place pour le chargement initial du formulaire, puis cochez à nouveau la case, le formulaire est valide et peut être soumis. Je ne sais pas ce qui me manque. Voici le code ng-change que j'ai jusqu'à présent:

    var phoneNumberRegex = /^\(?(\d{3})\)?[ .-]?(\d{3})[ .-]?(\d{4})$/;
    $scope.phoneNumberPattern = phoneNumberRegex;
    $scope.removeValidation = function() {
        if ($scope.cell._newUser === false) {
            $scope.request._number = '';
            $scope.phoneNumberPattern = /[0-9a-zA-Z]?/;
        } else {
            $scope.phoneNumberPattern = phoneNumberRegex;
        }
    };
83
Brian

C’est un problème intéressant, une validation angulaire complexe. Le violon suivant implémente ce que vous voulez:

http://jsfiddle.net/2G8gA/1/

Détails

J'ai créé une nouvelle directive, rpattern, qui est un mélange de ng-required d'Angular et du code ng-pattern de input[type=text]. Ce qu’il fait, c’est regarder l’attribut required du champ et en tenir compte lors de la validation avec regexp, c’est-à-dire si non requis, marquer le champ avec valid-pattern.

Remarques

  • La plupart du code est de Angular, adapté aux besoins de celui-ci.
  • Lorsque la case à cocher est cochée, le champ est obligatoire.
  • Le champ n'est pas masqué lorsque la case à cocher requise est fausse.
  • L'expression régulière est simplifiée pour la démo (valide 3 chiffres).

Une solution dirty (mais plus petite), si vous ne voulez pas de nouvelle directive, serait quelque chose comme:

$scope.phoneNumberPattern = (function() {
    var regexp = /^\(?(\d{3})\)?[ .-]?(\d{3})[ .-]?(\d{4})$/;
    return {
        test: function(value) {
            if( $scope.requireTel === false ) {
                return true;
            }
            return regexp.test(value);
        }
    };
})();

Et en HTML, aucune modification ne serait nécessaire:

<input type="text" ng-model="..." ng-required="requireTel"
    ng-pattern="phoneNumberPattern" />

En fait, cela équivaut à appeler la méthode notretest(), au lieu de RegExp.test(), qui prend en compte la required.

174

Ne rien enlever à la réponse impressionnante de Nikos, vous pouvez peut-être le faire plus simplement:

<form name="telForm">
  <input name="cb" type='checkbox' data-ng-modal='requireTel'>
  <input name="tel" type="text" ng-model="..." ng-if='requireTel' ng-pattern="phoneNumberPattern" required/>
  <button type="submit" ng-disabled="telForm.$invalid || telForm.$pristine">Submit</button>
</form>

Faites attention à la deuxième entrée: nous pouvons utiliser unng-ifpour contrôler le rendu et la validation dans les formulaires . Si la variable requireTel est non définie, la deuxième entrée serait non seulement masquée, mais pas rendue du tout, donc le formulaire passera la validation et le bouton deviendra activé, et vous obtiendrez ce dont vous avez besoin.

25
kumar_harsh

Modèle utilisé: 

 ng-pattern="/^\d{0,9}(\.\d{1,9})?$/"

Fichier de référence utilisé:

 '<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.js"></script>'

Exemple d'entrée:

 <input type="number" require ng-pattern="/^\d{0,9}(\.\d{1,9})?$/"><input type="submit">
5
Anil Singh

Je viens de rencontrer cela l'autre jour.

Ce que j'ai fait, ce qui semble plus facile que ce qui précède, consiste à définir le motif sur une variable de la portée et à y faire référence dans ng-pattern dans la vue. 

Lorsque "la case à cocher est décochée", je règle simplement la valeur de l'expression rationnelle sur /.*/ sur le rappel onChanged (si l'option est décochée). La sélection ng-pattern change et indique "OK, votre valeur est correcte". Le formulaire est maintenant valide. Je voudrais également supprimer les mauvaises données du terrain afin que vous ne disposiez pas d'un mauvais numéro de téléphone.

J'ai eu des problèmes supplémentaires sur ng-required, et a fait la même chose. Travaillé comme un charme.

2
jessewolfe

Définit la clé d'erreur de validation du modèle si ngModel $ viewValue ne correspond pas à une RegExp trouvée en évaluant l'expression angulaire donnée dans la valeur de l'attribut. Si l'expression renvoie un objet RegExp, elle est utilisée directement. Si l'expression renvoie une chaîne, elle sera convertie en une RegExp après l'avoir enveloppée dans des caractères ^ et $.

Il semble que la réponse la plus votée à cette question devrait être mise à jour, car lorsque je l’essaye, elle ne s’applique pas à la fonction test et la validation ne fonctionne pas.

Exemple tiré de docs angulaires fonctionne bien pour moi:

Modification des validateurs intégrés

html

<form name="form" class="css-form" novalidate>
  <div>
   Overwritten Email:
   <input type="email" ng-model="myEmail" overwrite-email name="overwrittenEmail" />
   <span ng-show="form.overwrittenEmail.$error.email">This email format is invalid!</span><br>
   Model: {{myEmail}}
  </div>
</form>

js

var app = angular.module('form-example-modify-validators', []);

app.directive('overwriteEmail', function() {
    var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+/=?^_`{|}~.-]+@example\.com$/i;

    return {
        require: 'ngModel',
        restrict: '',
        link: function(scope, Elm, attrs, ctrl) {
            // only apply the validator if ngModel is present and Angular has added the email validator
            if (ctrl && ctrl.$validators.email) {

                // this will overwrite the default Angular email validator
                ctrl.$validators.email = function(modelValue) {
                    return ctrl.$isEmpty(modelValue) || EMAIL_REGEXP.test(modelValue);
                };
             }
         }
     };
 });

Plunker

0
theodor