Validación de formularios en AngularJS al enviar: $dirty, $valid y $invalid

⚡ Resumen inteligente

La validación de formularios en AngularJS comprueba que los datos introducidos en un formulario sean correctos y completos antes de que lleguen al servidor. Aquí se describen cuatro enfoques, desde atributos HTML5 básicos y propiedades de ámbito hasta módulos de validación automática.

  • 🧩 Atributos HTML5: El atributo obligatorio y los tipos de entrada de correo electrónico, contraseña y número ofrecen comprobaciones nativas del navegador sin necesidad de scripts.
  • 🔍 Propiedades estatales: AngularJS expone las variables $dirty, $pristine, $valid y $invalid en cada control con nombre dentro de un formulario con nombre.
  • 🏷️ Requisito de nomenclatura: Tanto el formulario como cada control necesitan un atributo de nombre, ya que el estado de validación se gestiona como formName.controlName.
  • 🚫 Suprimir ventanas emergentes nativas: Agregar la palabra clave `novalidate` al formulario evita que el navegador intercepte el envío, permitiendo así que AngularJS lo gestione.
  • ???? Visualización de mensajes: El módulo ngMessages reemplaza las directivas ng-show apiladas y muestra un error a la vez en orden de prioridad.
  • ⚙️ Validación automática: El módulo jcs-autoValidate genera mensajes de error para cada control sin necesidad de marcado personalizado.
  • 🔘 Comentarios de envío: Un botón de Ladda muestra un indicador de carga mientras se procesa una solicitud, lo que indica al usuario el progreso.

Validación de formulario en AngularJS

Validación de formularios En AngularJS, la validación consiste en verificar que los datos introducidos en un formulario sean correctos y completos. Cuando un usuario envía el formulario, se realiza primero la validación, antes de que los datos se envíen al servidor. Este proceso garantiza, en la medida de lo posible, que los campos de entrada se hayan rellenado correctamente.

En un ejemplo práctico, supongamos un sitio web que requiere completar un formulario de registro antes de otorgar acceso completo. La página de registro tendría campos para ingresar nombre de usuario, contraseña, correo electrónico, etc.

Por ejemplo, la dirección de correo electrónico siempre debe estar en el formato nombre de usuario@sitio.dominioSi alguien introduce solo el nombre de usuario, la validación debería fallar. La validación realiza estas comprobaciones básicas antes de que los datos se envíen al servidor para su posterior procesamiento.

⚠️ Nota de versión: AngularJS (la rama 1.x) llegó al final de su ciclo de vida el 31 de diciembre de 2021 y ya no recibe actualizaciones de seguridad. Las técnicas que se describen a continuación siguen siendo válidas para aplicaciones antiguas; Angular moderno realiza la misma tarea con formularios reactivos o basados ​​en plantillas.

Validación de formularios usando HTML5

La validación de formularios es el proceso de prevalidar la información ingresada en un formulario web antes de enviarla al servidor. Es preferible validar en el lado del cliente, ya que genera mucha menos sobrecarga que volver a presentar el formulario después de un intercambio de datos.

El siguiente ejemplo muestra un formulario de registro sencillo en el que el usuario introduce un nombre de usuario, una contraseña, una dirección de correo electrónico y su edad. El formulario incluye controles de validación que garantizan que la información se introduzca correctamente.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Event Registration</title>
    <link rel="stylesheet" href="lib/bootstrap.css">
    <script src="https://code.angularjs.org/1.8.3/angular.min.js"></script>
</head>
<body ng-app="sampleApp">
<h1>Guru99 Global Event</h1>

<form>
    Enter your user name:
    <input type="text" name="name" required><br><br>

    Enter your password:
    <input type="password" name="password"><br><br>

    Enter your email:
    <input type="email" name="email"><br><br>

    Enter your age:
    <input type="number" name="age"><br><br>

    <input type="submit" value="Submit">
</form>
</body>
</html>

⚠️ Se han aplicado correcciones a todos los listados de esta página. Los originales declararon chrset="UTF 8", que no es ni un atributo válido ni una codificación válida, y cargó AngularJS tres veces. angular-route.js primero, lo cual se produce porque el módulo de ruta se registra contra un marco que no se ha cargado, luego angular.min.js y angular.js, la misma biblioteca dos veces. También sacaron bootstrap.css a través de un <script> etiqueta, por lo que nunca se aplicó ningún estilo. Cada listado ahora carga una biblioteca, versión 1.8.3, y enlaza la hoja de estilos correctamente. El relleno del diseño se construyó a partir de repeticiones &nbsp; Las entidades han sido eliminadas.

Code Explicación

  1. Para el tipo de entrada de texto, el required Este atributo significa que el cuadro de texto no puede estar vacío cuando se envía el formulario.
  2. El siguiente tipo de entrada es contraseña. Dado que el tipo está marcado como contraseña, el texto introducido en el campo se oculta.
  3. Dado que el tipo de entrada se especifica como correo electrónico, el texto en el cuadro debe coincidir con el patrón. nombre@sitio.dominio.
  4. Cuando el tipo de entrada está marcado como número, los caracteres que se escriban desde el teclado simplemente no serán aceptados por el campo.

Resultado

Para ver la validación en acción, haga clic en Enviar sin introducir nada.

Aparece una ventana emergente que indica que el campo debe rellenarse, por lo que el control marcado como obligatorio bloquea el envío si se deja vacío.

Al introducir un valor en el control de contraseña, el símbolo '*' oculta los caracteres.

Al introducir una dirección de correo electrónico con formato incorrecto y hacer clic en Enviar, aparece una ventana emergente que solicita el símbolo @. Además, los caracteres introducidos en el campo de edad no aparecen, ya que este solo acepta números.

Las ventanas emergentes del navegador se configuran rápidamente, pero su texto y estilo no se pueden modificar. Ahí es donde entran en juego las propiedades de validación de AngularJS.

Validación de formulario usando $dirty, $valid, $invalid, $pristine

AngularJS Proporciona sus propias propiedades para la validación. Las siguientes propiedades se exponen en cada control con nombre:

  • $sucio – El usuario ha interactuado con el control.
  • $válido – El contenido del campo es válido.
  • $inválido – El contenido del campo no es válido.
  • $prístino – El usuario aún no ha interactuado con el control.

A continuación se detallan los pasos para realizar la validación con AngularJS.

Paso 1) Utilice el novalidate propiedad al declarar el formulario. Esto le indica al navegador que la validación será gestionada por AngularJS.

Paso 2) Asegúrese de que el formulario tenga un nombre definido, ya que ese nombre se utiliza para alcanzar el estado de validación.

Paso 3) Asegúrese de que cada control también tenga un name atributo, por la misma razón. Un control sin nombre nunca se registra en el formulario.

Paso 4) Utilice el ng-mostrar Directiva para comprobar las propiedades $dirty, $invalid y $valid.

El siguiente ejemplo contiene un único campo de texto donde el usuario introduce el nombre del tema. Si se deja en blanco, se activa un error de validación y se muestra el mensaje.

<form ng-app="DemoApp" ng-controller="DemoController"
      name="myForm" novalidate>
    <p>Topic Name:<br>
        <input type="text" name="user" ng-model="user" required>

        <span style="color:red"
              ng-show="myForm.user.$dirty && myForm.user.$invalid">
            <span ng-show="myForm.user.$error.required">Username is required</span>
        </span>
    </p>
    <p>
        <input type="submit" ng-disabled="myForm.$invalid">
    </p>
</form>

<script>
    var app = angular.module("DemoApp", []);

    app.controller("DemoController", function($scope) {
        // Seed the textbox so the form starts in a valid state
        $scope.user = "AngularJS";
    });
</script>

⚠️ Se corrigieron dos errores de lógica. El original deshabilitó el botón con ng-disabled="myForm.user.$dirty && myForm.user.$invalid". Porque $dirty es falso hasta que el usuario toque el campo, el botón permaneció habilitada en un formulario vacío e intacto, el caso exacto que se suponía que debía bloquear; myForm.$invalid cubre ambos. El original también envolvió el valor predeterminado en $scope.Display = function () { $scope.user = 'Angular'; }, una función que nunca se llamó, por lo que el cuadro de texto se abrió vacío a pesar de que el texto indicaba que mostraba “AngularJS”. La asignación ahora se realiza directamente, con el valor que el texto circundante cita.

Code Explicación

  1. El formulario se denomina “myForm”. Esto es necesario para poder acceder a sus controles de validación.
  2. El novalidate Esta propiedad impide que el navegador realice la validación, por lo que AngularJS puede hacerlo en su lugar.
  3. La directiva ng-show comprueba las propiedades “$dirty” e “$invalid”. Si el cuadro de texto se ha modificado, $dirty es verdadera; si su valor está vacío, $invalid es verdadera. Cuando ambas son verdaderas, se muestra el elemento span con el texto rojo.
  4. La comprobación anidada lee la propiedad “$error.required”, que es verdadera siempre que un control obligatorio no tenga ningún valor, y muestra “El nombre de usuario es obligatorio”.
  5. El botón de envío está deshabilitado a través de ng-disabled siempre que el formulario en su conjunto sea inválido.
  6. El controlador establece el valor inicial del cuadro de texto en "AngularJS", de modo que el formulario se abre en un estado válido y la validación es más fácil de observar a medida que se borra el texto.

Resultado

Cuando se muestra el formulario por primera vez, el cuadro de texto muestra "AngularJS" y el botón de envío está habilitado. Tan pronto como se elimina el texto, aparece el mensaje de error y el botón se desactiva.

La captura de pantalla anterior muestra dos cosas:

  • El botón de envío está deshabilitado.
  • No hay ningún nombre de tema en el cuadro de texto Tema, por lo que se muestra el mensaje de error "Se requiere nombre de usuario".

Cómo mostrar errores de validación con ngMessages

El patrón anterior funciona, pero no es escalable. Un campo con cuatro restricciones necesita cuatro anidados. ng-show se extienden, y cuando varios de ellos fallan a la vez, todos los mensajes aparecen juntos. ngMessages El módulo, distribuido por separado por el equipo de AngularJS, resuelve ambos problemas: muestra un mensaje a la vez, en el orden en que se escriben.

Carga el módulo y agrégalo como dependencia.

<script src="https://code.angularjs.org/1.8.3/angular-messages.js"></script>
<script>
    angular.module("DemoApp", ["ngMessages"]);
</script>

El código se lee entonces como una lista de reglas en lugar de una pila de condiciones.

<input type="text" name="user" ng-model="user"
       required ng-minlength="4" ng-maxlength="20">

<div style="color:red" ng-messages="myForm.user.$error"
     ng-if="myForm.user.$dirty">
    <div ng-message="required">A topic name is required</div>
    <div ng-message="minlength">Use at least 4 characters</div>
    <div ng-message="maxlength">Use no more than 20 characters</div>
</div>

Tres detalles hacen que esto funcione bien en la práctica. El ng-messages Los atributos apuntan al control. $error objeto en lugar de un booleano, por lo que no es necesario repetir ninguna condición. Solo la primera coincidencia ng-message renderiza, lo que significa que un campo en blanco informa que es obligatorio en lugar de quejarse también de su longitud. Agregar ng-messages-multiple Revierte ese comportamiento cuando realmente es necesario enumerar cada fallo.

Envuelvaping el bloque en ng-if="myForm.user.$dirty" Mantiene el formulario en silencio hasta que el usuario haya escrito algo. Sustituyendo $touched por la $dirty Esto retrasa aún más el mensaje, hasta que el foco se aleja del campo, lo cual suele ser la opción más amigable en un formulario de registro largo.

Una advertencia: ngMessages Se envía como un archivo separado, por lo que si se olvida la etiqueta de script o la dependencia del módulo, el bloque no renderiza nada en absoluto, sin ningún mensaje de error en la consola que lo explique.

Escribir mensajes a mano es preciso pero repetitivo. La siguiente sección describe un módulo que los genera automáticamente.

Validación de formulario usando AngularJS Auto Validate

AngularJS puede validar automáticamente todos los controles de un formulario, sin necesidad de código personalizado para la validación ni para los mensajes de error. Esto se logra mediante la inclusión de un módulo de la comunidad llamado "jcs-autoValidate".

Con este módulo instalado, no se necesita ningún código especial para ejecutar la validación o mostrar los mensajes; todo se gestiona dentro de jcs-autoValidate.

El siguiente ejemplo muestra un formulario sencillo con un único campo de texto obligatorio. Si este campo no se rellena, se mostrará un mensaje de error.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Event Registration</title>
    <link rel="stylesheet" href="lib/bootstrap.css">
    <script src="https://code.angularjs.org/1.8.3/angular.min.js"></script>
    <script src="lib/jcs-auto-validate.min.js"></script>
</head>
<body>
<h1>Guru99 Event</h1>

<div ng-app="DemoApp">
    <form name="myForm" novalidate>
        <div class="form-group">
            <label for="user">Topic Name:</label>
            <input class="form-control" type="text"
                   id="user" name="user" ng-model="user" required>
        </div>
        <div class="form-group">
            <input type="submit">
        </div>
    </form>
</div>

<script>
    var app = angular.module('DemoApp', ['jcs-autoValidate']);
</script>
</body>
</html>

⚠️ Corrección: El original identificó el control con id="user" solamente. jcs-autoValidate llega al control a través del formulario, por lo que un name El atributo es obligatorio y el mensaje nunca apareció sin él. El original también cargó dos versiones diferentes de AngularJS, 1.6.4 desde el Google CDN junto con 1.6.9, y nunca vinculado Bootstrap aunque el ejemplo depende de su form-group y form-control clases para posicionar el texto de error.

💡 Nota: jcs-autoValidate es un proyecto de la comunidad y ya no se mantiene activamente. Sigue siendo utilizable en aplicaciones AngularJS existentes, pero el integrado ngMessages El enfoque mostrado anteriormente es la opción más segura para cualquier novedad.

Code Explicación

  1. Se incluye el script “jcs-auto-validate.js”, que contiene toda la funcionalidad de validación automática.
  2. Cada control y el div que lo rodea se colocan dentro de una clase "form-group", que es donde el módulo inserta su mensaje.
  3. El control lleva tanto un id como un name, y Bootstrap suministra el form-control estilo
  4. El módulo “jcs-autoValidate” figura como dependencia del módulo AngularJS.

Resultado

Por defecto, el formulario se muestra exactamente como está escrito.

Al enviar el formulario vacío, se muestra el mensaje "Este campo es obligatorio", generado íntegramente por jcs-autoValidate. Una vez validado el formulario, la pregunta que queda es qué ve el usuario mientras se envía.

Comentarios de usuarios con botones Ladda

Los botones “Ladda” son un marco construido sobre JavaScript que proporciona un efecto visual a los botones cuando se pulsan.

Si se asigna el atributo "ladda" a un botón y se pulsa, se muestra un efecto de giro. Hay diferentes estilos de datos disponibles para obtener efectos visuales adicionales.

El siguiente ejemplo muestra un formulario sencillo con un botón de envío. Al pulsar el botón, aparece un efecto de giro.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Event Registration</title>
    <link rel="stylesheet" href="lib/bootstrap.css">
    <script src="https://code.angularjs.org/1.8.3/angular.min.js"></script>
    <script src="lib/angular-ladda.min.js"></script>
</head>
<body>
<h1>Guru99 Event</h1>

<div ng-app="DemoApp" ng-controller="DemoController">
    <form name="myForm" novalidate ng-submit="submit()">
        <button class="btn btn-primary" type="submit"
                ladda="submitting" name="sbutton"
                data-style="expand-right">Submit</button>
    </form>
</div>

<script>
    var app = angular.module('DemoApp', ['angular-ladda']);

    app.controller('DemoController', function($scope) {
        $scope.submitting = false;

        $scope.submit = function() {
            $scope.submitting = true;
        };
    });
</script>
</body>
</html>

⚠️ Corrección: el original cargado angular-ladda.js y angular-ladda.min.js juntos, lo que registra el mismo módulo dos veces, y nuevamente se cargaron dos versiones de AngularJS. También se enumeró jcs-autoValidate como una dependencia que este ejemplo nunca utiliza. Aquí se carga una copia de cada biblioteca.

Code Explicación

  1. El evento "ng-enviarLa directiva ” llama a una función llamada “submit”, que cambia el atributo ladda del botón.
  2. El atributo ladda pertenece al marco de Ladda y es lo que agrega el efecto de giro. Su valor está vinculado a la submitting variable.
  3. La propiedad data-style es otro atributo de Ladda que selecciona un efecto visual diferente.
  4. Para que el framework funcione, es necesario añadir el módulo 'angular-ladda' a la aplicación AngularJS.
  5. El submitting La variable se inicializa a falso, por lo que el botón comienza sin el efecto de giro.
  6. La función de envío establece submitting a verdadero, lo que aplica el efecto. En una aplicación real, se restablecería a falso una vez que el servidor responda; de lo contrario, el botón giraría indefinidamente.

Resultado

Cuando se muestra el formulario por primera vez, el botón de envío se muestra en su forma simple.

Cuando se presiona el botón, el submitting La variable se establece en verdadero. Ese valor llega al atributo "ladda" del botón, produciendo el efecto de giro.

Preguntas Frecuentes

$dirty se vuelve verdadero cuando el valor cambia. $touched se vuelve verdadero cuando el campo pierde el foco. Use $touched para retrasar un error hasta que el usuario haya pasado a otra cosa, lo que se siente menos agresivo mientras intentaping.

Agregue la directiva ng-pattern con una expresión regular, por ejemplo ng-pattern=”/^[0-9]{6}$/”. El error se mostrará entonces como $error.pattern, que ngMessages puede reportar como cualquier restricción integrada.

Sí. Las herramientas de IA leen el marcado y generan bloques `required`, `ng-pattern` y `ngMessages` coincidentes. Siempre revise las expresiones regulares, ya que los patrones de correo electrónico y teléfono generados suelen rechazar entradas válidas.

Los asistentes de IA comprueban rápidamente las tres causas habituales: la falta del atributo name en el formulario o control, la falta de ng-model y que no se haya habilitado novalidate, por lo que el navegador intercepta primero el envío.

No. Mejora la experiencia y reduce los viajes de ida y vuelta, pero cualquiera puede eludirlo con herramientas para desarrolladores. Cada regla aplicada en el navegador debe aplicarse nuevamente en el servidor.

Resumir este post con: