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.

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 Las entidades han sido eliminadas.
Code Explicación
- Para el tipo de entrada de texto, el
requiredEste atributo significa que el cuadro de texto no puede estar vacío cuando se envía el formulario. - 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.
- 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.
- 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
- El formulario se denomina “myForm”. Esto es necesario para poder acceder a sus controles de validación.
- El
novalidateEsta propiedad impide que el navegador realice la validación, por lo que AngularJS puede hacerlo en su lugar. - 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.
- 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”.
- El botón de envío está deshabilitado a través de
ng-disabledsiempre que el formulario en su conjunto sea inválido. - 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
- Se incluye el script “jcs-auto-validate.js”, que contiene toda la funcionalidad de validación automática.
- 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.
- El control lleva tanto un id como un
name, y Bootstrap suministra elform-controlestilo - 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
- El evento "ng-enviarLa directiva ” llama a una función llamada “submit”, que cambia el atributo ladda del botón.
- El atributo ladda pertenece al marco de Ladda y es lo que agrega el efecto de giro. Su valor está vinculado a la
submittingvariable. - La propiedad data-style es otro atributo de Ladda que selecciona un efecto visual diferente.
- Para que el framework funcione, es necesario añadir el módulo 'angular-ladda' a la aplicación AngularJS.
- El
submittingLa variable se inicializa a falso, por lo que el botón comienza sin el efecto de giro. - La función de envío establece
submittinga 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.














