Validaciones básicas
Los formularios template-driven de Angular proporcionan un sistema de validación integrado que aprovecha los atributos HTML5 estándar para establecer reglas de validación directamente en el template. Esta aproximación resulta intuitiva para desarrolladores familiarizados con HTML, ya que utiliza atributos nativos del navegador combinados con la funcionalidad de Angular.
Atributos HTML5 de validación
Angular reconoce automáticamente los atributos de validación HTML5 cuando se utilizan en elementos que tienen la directiva ngModel
. Los validadores más comunes incluyen:
Validación de campos obligatorios:
<input
type="text"
name="nombre"
[(ngModel)]="usuario.nombre"
required
#nombre="ngModel">
Validación de longitud mínima y máxima:
<input
type="password"
name="password"
[(ngModel)]="usuario.password"
required
minlength="8"
maxlength="20"
#password="ngModel">
Validación de formato de email:
<input
type="email"
name="email"
[(ngModel)]="usuario.email"
required
email
#email="ngModel">
Validación con patrones personalizados:
<input
type="text"
name="telefono"
[(ngModel)]="usuario.telefono"
pattern="[0-9]{9}"
#telefono="ngModel"
placeholder="Ejemplo: 123456789">
Variables de plantilla para validación
La sintaxis de variable de plantilla #campo="ngModel"
es fundamental para acceder al estado de validación de cada campo. Esta variable expone propiedades que permiten conocer el estado actual del input:
<form #formularioUsuario="ngForm">
<input
type="text"
name="username"
[(ngModel)]="usuario.username"
required
minlength="3"
#username="ngModel">
<input
type="email"
name="email"
[(ngModel)]="usuario.email"
required
email
#email="ngModel">
</form>
Estados de validación
Cada campo con ngModel
mantiene varios estados de validación que se actualizan automáticamente según las interacciones del usuario:
Estados de validez:
valid
: El campo cumple todas las reglas de validacióninvalid
: El campo no cumple una o más reglas de validaciónerrors
: Objeto que contiene los errores específicos del campo
Estados de interacción:
touched
: El usuario ha enfocado y luego salido del campountouched
: El campo no ha recibido foco aúnpristine
: El valor del campo no ha sido modificadodirty
: El valor del campo ha sido modificado
Ejemplo de acceso a estados:
<form #formulario="ngForm">
<input
type="text"
name="nombre"
[(ngModel)]="usuario.nombre"
required
minlength="2"
#nombre="ngModel">
<!-- Mostrar información de estado (solo para debug) -->
<div>
<p>Válido: {{ nombre.valid }}</p>
<p>Tocado: {{ nombre.touched }}</p>
<p>Pristine: {{ nombre.pristine }}</p>
<p>Errores: {{ nombre.errors | json }}</p>
</div>
</form>
Objeto errors
El objeto errors
contiene información detallada sobre qué validaciones específicas han fallado. Cada validador que falla añade una propiedad al objeto:
// Ejemplo de objeto errors para un campo inválido:
{
required: true, // Campo obligatorio vacío
minlength: { // Longitud mínima no alcanzada
requiredLength: 8,
actualLength: 5
},
email: true // Formato de email inválido
}
Acceso a errores específicos en el template:
<input
type="email"
name="correo"
[(ngModel)]="usuario.correo"
required
email
minlength="5"
#correo="ngModel">
<!-- Verificar errores específicos -->
<div>
<p>¿Campo requerido? {{ correo.errors?.['required'] }}</p>
<p>¿Email inválido? {{ correo.errors?.['email'] }}</p>
<p>¿Muy corto? {{ correo.errors?.['minlength'] }}</p>
</div>
Validación de formulario completo
El formulario como conjunto también mantiene su propio estado de validación, que se deriva del estado de todos sus campos:
<form #miFormulario="ngForm">
<input
type="text"
name="nombre"
[(ngModel)]="datos.nombre"
required
#nombre="ngModel">
<input
type="email"
name="email"
[(ngModel)]="datos.email"
required
email
#email="ngModel">
<!-- Estado del formulario completo -->
<div>
<p>Formulario válido: {{ miFormulario.valid }}</p>
<p>Formulario tocado: {{ miFormulario.touched }}</p>
<p>Formulario pristine: {{ miFormulario.pristine }}</p>
</div>
</form>
La validación se ejecuta automáticamente cada vez que el usuario modifica el valor de un campo, y Angular actualiza todos los estados correspondientes. Esta reactividad permite crear interfaces de usuario que respondan inmediatamente a las acciones del usuario, proporcionando retroalimentación en tiempo real sobre la validez de los datos introducidos.
Mensajes de error
Una vez establecidas las reglas de validación, el siguiente paso es mostrar mensajes de error claros y útiles al usuario. Angular proporciona un sistema flexible para mostrar mensajes condicionalmente basándose en el estado de validación de cada campo, utilizando la nueva sintaxis de control de flujo @if
para crear una experiencia de usuario intuitiva.
Mensajes condicionales con @if
La sintaxis @if
de Angular permite mostrar mensajes de error únicamente cuando se cumplen ciertas condiciones. La estrategia más común es mostrar errores solo después de que el usuario haya interactuado con el campo:
<form #contactoForm="ngForm">
<div class="campo-grupo">
<label for="nombre">Nombre completo</label>
<input
type="text"
id="nombre"
name="nombre"
[(ngModel)]="contacto.nombre"
required
minlength="2"
#nombre="ngModel"
class="form-control">
@if (nombre.invalid && nombre.touched) {
<div class="mensajes-error">
@if (nombre.errors?.['required']) {
<small class="error">El nombre es obligatorio</small>
}
@if (nombre.errors?.['minlength']) {
<small class="error">El nombre debe tener al menos 2 caracteres</small>
}
</div>
}
</div>
</form>
Estrategias para mostrar errores
Existen diferentes momentos apropiados para mostrar mensajes de error según la experiencia de usuario deseada:
Mostrar errores después de tocar el campo:
<input
type="email"
name="email"
[(ngModel)]="usuario.email"
required
email
#email="ngModel">
@if (email.invalid && email.touched) {
<div class="error-container">
@if (email.errors?.['required']) {
<span class="mensaje-error">El email es obligatorio</span>
}
@if (email.errors?.['email']) {
<span class="mensaje-error">Introduce un email válido</span>
}
</div>
}
Mostrar errores después de modificar el campo:
<input
type="password"
name="password"
[(ngModel)]="usuario.password"
required
minlength="8"
maxlength="20"
#password="ngModel">
@if (password.invalid && password.dirty) {
<div class="alertas">
@if (password.errors?.['required']) {
<p class="alerta-error">La contraseña es obligatoria</p>
}
@if (password.errors?.['minlength']) {
<p class="alerta-error">
La contraseña debe tener al menos 8 caracteres
(actual: {{ password.errors?.['minlength'].actualLength }})
</p>
}
</div>
}
Mensajes de error específicos por validador
Cada tipo de validación puede tener su mensaje personalizado que proporcione información clara sobre cómo corregir el error:
<div class="formulario-registro">
<input
type="text"
name="telefono"
[(ngModel)]="usuario.telefono"
required
pattern="[0-9]{9}"
#telefono="ngModel"
placeholder="123456789">
@if (telefono.invalid && telefono.touched) {
<div class="errores-validacion">
@if (telefono.errors?.['required']) {
<span class="error-requerido">El teléfono es obligatorio</span>
}
@if (telefono.errors?.['pattern']) {
<span class="error-formato">
El teléfono debe contener exactamente 9 dígitos
</span>
}
</div>
}
</div>
Ejemplo con validación de longitud detallada:
<textarea
name="comentario"
[(ngModel)]="feedback.comentario"
required
minlength="10"
maxlength="500"
#comentario="ngModel"
rows="4">
</textarea>
@if (comentario.invalid && comentario.dirty) {
<div class="feedback-errores">
@if (comentario.errors?.['required']) {
<div class="error">Por favor, escribe un comentario</div>
}
@if (comentario.errors?.['minlength']) {
<div class="error">
El comentario debe tener al menos 10 caracteres
(faltan {{ comentario.errors?.['minlength'].requiredLength - comentario.errors?.['minlength'].actualLength }})
</div>
}
@if (comentario.errors?.['maxlength']) {
<div class="error">
El comentario excede el límite de 500 caracteres
(sobran {{ comentario.errors?.['maxlength'].actualLength - comentario.errors?.['maxlength'].requiredLength }})
</div>
}
</div>
}
Estilos CSS para campos inválidos
Angular añade automáticamente clases CSS a los campos según su estado de validación. Estas clases permiten aplicar estilos visuales que refuercen el feedback de validación:
/* Estilos para campos válidos e inválidos */
.form-control.ng-valid.ng-touched {
border-color: #28a745;
box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);
}
.form-control.ng-invalid.ng-touched {
border-color: #dc3545;
box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);
}
/* Estilos para mensajes de error */
.mensajes-error {
margin-top: 0.25rem;
}
.mensaje-error {
display: block;
color: #dc3545;
font-size: 0.875rem;
margin-top: 0.25rem;
}
.error-container {
background-color: #f8d7da;
border: 1px solid #f5c6cb;
border-radius: 0.25rem;
padding: 0.5rem;
margin-top: 0.5rem;
}
Ejemplo completo con estilos integrados:
<form #perfilForm="ngForm" class="formulario-perfil">
<div class="grupo-campo">
<label for="username">Nombre de usuario</label>
<input
type="text"
id="username"
name="username"
[(ngModel)]="perfil.username"
required
minlength="3"
maxlength="15"
pattern="[a-zA-Z0-9_]+"
#username="ngModel"
class="form-control"
[class.campo-invalido]="username.invalid && username.touched">
@if (username.invalid && username.touched) {
<div class="contenedor-errores">
@if (username.errors?.['required']) {
<div class="mensaje-error">
<i class="icon-warning"></i>
El nombre de usuario es obligatorio
</div>
}
@if (username.errors?.['minlength']) {
<div class="mensaje-error">
<i class="icon-warning"></i>
Debe tener al menos 3 caracteres
</div>
}
@if (username.errors?.['maxlength']) {
<div class="mensaje-error">
<i class="icon-warning"></i>
No puede exceder 15 caracteres
</div>
}
@if (username.errors?.['pattern']) {
<div class="mensaje-error">
<i class="icon-warning"></i>
Solo se permiten letras, números y guiones bajos
</div>
}
</div>
}
</div>
</form>
Mensajes de estado del formulario
Además de los mensajes por campo, es útil mostrar mensajes generales sobre el estado del formulario completo:
<form #registroForm="ngForm">
<!-- Campos del formulario... -->
@if (registroForm.invalid && registroForm.touched) {
<div class="alerta-formulario">
<h4>Por favor, corrige los siguientes errores:</h4>
<ul>
@if (nombre.invalid) {
<li>Completa el campo nombre correctamente</li>
}
@if (email.invalid) {
<li>Introduce un email válido</li>
}
@if (password.invalid) {
<li>La contraseña debe cumplir los requisitos</li>
}
</ul>
</div>
}
<button
type="submit"
[disabled]="registroForm.invalid"
class="btn-submit">
Registrarse
</button>
</form>
La combinación de mensajes específicos por campo y feedback visual a través de CSS proporciona una experiencia de usuario clara y profesional. Los usuarios reciben información inmediata sobre qué necesita ser corregido y cómo hacerlo, lo que reduce la frustración y mejora la tasa de completación de formularios.
Fuentes y referencias
Documentación oficial y recursos externos para profundizar en Angular
Documentación oficial de Angular
Alan Sastre
Ingeniero de Software y formador, CEO en CertiDevs
Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Angular es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.
Más tutoriales de Angular
Explora más contenido relacionado con Angular y continúa aprendiendo con nuestros tutoriales gratuitos.
Aprendizajes de esta lección
- Comprender cómo Angular integra validaciones básicas usando atributos HTML5 en formularios template-driven.
- Aprender a utilizar variables de plantilla para acceder a estados de validación de campos.
- Identificar y manejar los diferentes estados de validación y errores específicos de cada campo.
- Implementar mensajes de error condicionales para mejorar la experiencia del usuario.
- Aplicar estilos CSS para reflejar visualmente el estado de validación de los campos y formularios.