Angularjs dynamic ng-pattern validation


Tengo un formulario que si una casilla de verificación es false obliga a validar una entrada de texto utilizando la directiva ng-required. Si la casilla de verificación es true, el campo se oculta y el ng-required se establece en false.

El problema es que también tengo una expresión regular para la validación especificada en la entrada, además de utilizar la directiva angular ng-pattern. El problema con el que me estoy topando es que si un usuario rellena un número de teléfono no válido, marca la casilla para desactivar esa entrada (y en consecuencia no necesita validación adicional) el formulario no permitirá el envío ya que no es válido en función del patrón ng.

Intenté resolver este problema agregando una función ng-change para establecer el modelo de entrada en null, sin embargo, el patrón ng y, por lo tanto, el campo sigue siendo inválido en el conjunto inicial de la casilla de verificación en false. Sin embargo, si desmarque la casilla, volviendo todo a la carga inicial del formulario, luego marque la casilla nuevamente, el formulario es válido y puede enviarse. No estoy seguro de lo que me estoy perdiendo. Aqui es el código ng-change que tengo hasta ahora:

    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;
        }
    };
Author: Brian, 2013-09-19

7 answers

Este es un problema interesante, la validación angular compleja. El siguiente violín implementa lo que quieres:

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

Detalles

He creado una nueva directiva, rpattern, que es una mezcla de ng-required de Angular y el código ng-pattern de input[type=text]. Lo que hace es observar el atributo required del campo y tenerlo en cuenta al validar con regexp, es decir, si no es necesario marcar el campo como valid-pattern.

Notas

  • La mayoría del código es de Angular, adaptado a las necesidades de este.
  • Cuando la casilla de verificación está marcada, el campo es obligatorio.
  • El campo no se oculta cuando la casilla de verificación requerida es falsa.
  • La expresión regular se simplifica para la demo (válida es de 3 dígitos).

Una sucia (pero más pequeña) solución, si no quieres una nueva directiva, sería algo así como:

$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);
        }
    };
})();

Y en HTML no se requerirían cambios:

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

Esto en realidad engaña a angular para que llame a nuestro test() método, en lugar de RegExp.test(), que tiene en cuenta el required.

 173
Author: Nikos Paraskevopoulos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-10 16:23:57

No quitando nada de la impresionante respuesta de Nikos, tal vez puedas hacer esto más simplemente:

<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>

Preste atención a la segunda entrada: Podemos usar un ng-if para controlar el renderizado y la validación en formularios. Si la variable requireTel no está configurada, la segunda entrada no solo se ocultará, sino que no se renderizará en absoluto, por lo que el formulario pasará la validación y el botón se habilitará, y obtendrá lo que necesita.

 25
Author: kumar_harsh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-23 08:30:33

Patrón usado:

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

Archivo de referencia utilizado:

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

Ejemplo de Entrada:

 <input type="number" require ng-pattern="/^\d{0,9}(\.\d{1,9})?$/"><input type="submit">
 5
Author: Anil Singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-07 17:43:35

 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.js"></script>
<input type="number" require ng-pattern="/^\d{0,9}(\.\d{1,9})?$/"><input type="submit">
 2
Author: Jijo Paulose,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-08 06:07:42

Me encontré con esto el otro día.

Lo que hice, que parece más fácil que lo anterior, es establecer el patrón en una variable en el alcance y referirme a él en ng-patrón en la vista.

Cuando "la casilla de verificación está desactivada" simplemente establezco el valor regex a /.* / en la devolución de llamada onChanged (si va a desmarcado). ng-pattern recoge ese cambio y dice "OK, tu valor está bien". El formulario ahora es válido. También eliminaría los datos incorrectos del campo para que no tenga un mal aparente teléfono # sentado allí.

Tuve problemas adicionales en torno a ng-required, e hice lo mismo. Funcionó a las mil maravillas.

 2
Author: jessewolfe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-03 18:29:00

Establece la clave de error de validación del patrón si ngModel view viewValue no coincide con una expresión regular encontrada al evaluar la expresión Angular dada en el valor del atributo. Si la expresión se evalúa como un objeto RegExp, se usa directamente. Si la expresión se evalúa como una cadena, se convertirá en una expresión regular después de envolverla en caracteres ^ y characters.

Parece que una respuesta más votada en esta pregunta debe actualizarse, porque cuando la pruebo, no se aplica test la función y la validación no funcionan.

Ejemplo de Angular docs funciona bien para mí:

Modificando validadores integrados

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

Émbolo

 0
Author: theodor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-26 19:20:58

Puede usar el sitio https://regex101.com / para construir su propio patrón específico para algún país:

Por ejemplo, Polonia:

-pattern = xxxxxxxxx OR xxx-xxx-xxx OR xxx xxx xxx 
-regexp ="^\d{9}|^\d{3}-\d{3}-\d{3}|^\d{3}\s\d{3}\s\d{3}"
 -1
Author: Lepton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-15 19:21:13