Aplicar clases dinámicas en Angular te permite cambiar estilos según el estado de un formulario o componente, sin mover elementos del DOM ni romper la experiencia visual. Esta técnica usa class binding y validadores reactivos para mostrar mensajes de error de forma elegante, ideal para desarrolladores frontend que buscan formularios usables y limpios.
Por qué evitar ngIf para mostrar errores en formularios
Usar *ngIf parece la solución obvia: si el control es inválido, renderizas el mensaje; si es válido, lo ocultas. El problema aparece cuando pruebas el formulario en el navegador.
Cuando *ngIf evalúa la condición, renderiza o elimina el elemento del DOM. Eso significa que el espacio que ocupa el mensaje de error aparece y desaparece, empujando los inputs que están debajo. Si un usuario está llenando un formulario y los campos saltan cada vez que aparece un error, la usabilidad se rompe.
¿Qué hace ngIf en Angular? Renderiza o elimina un elemento del DOM según una condición booleana. No lo oculta visualmente, lo quita por completo, lo que puede mover otros elementos de la página.
La alternativa es mantener el elemento siempre en el DOM y solo activar una clase CSS que controle su visibilidad con opacity.
Cómo funciona el class binding con [class.nombre] en Angular
El class binding es una forma de property binding que activa o desactiva una clase CSS según una expresión booleana. La sintaxis es directa:
html
<span class="message-error" [class.show]="nameControl.invalid && nameControl.touched">
Nombre inválido
</span>
Aquí, show es el nombre de la clase que quieres activar. Puede ser cualquier nombre que tengas definido en tu CSS. La clase se agrega al elemento solo cuando la condición se cumple [03:45].
Cómo configurar los validadores required y minLength
En el controlador del formulario reactivo, defines las reglas que activarán el estado inválido:
typescript
nameControl = new FormControl('', [
Validators.required,
Validators.minLength(3)
]);
Validators.required obliga a que el campo no esté vacío.
Validators.minLength(3) exige al menos 3 caracteres, similar a cómo se valida la longitud mínima de un password [01:10].
- La propiedad
touched verifica si el usuario ya interactuó con el input, evitando mostrar errores antes de tiempo.
¿Qué es la propiedad touched en un FormControl? Es un booleano que se vuelve true cuando el usuario hace foco en el input y luego sale de él. Sirve para no mostrar errores antes de que la persona haya interactuado con el campo.
Cómo ocultar el mensaje con opacity y transition
En el CSS, el mensaje siempre está en el DOM, pero invisible por defecto:
css
.message-error {
background: repeating-linear-gradient(...);
color: white;
padding: 8px;
opacity: 0;
transition: all linear 0.5s;
}
.message-error.show {
opacity: 1;
}
La clave está en la transition: si olvidas la s en el tiempo (por ejemplo escribir 5 en lugar de 0.5s), la animación no funciona [06:50]. El detalle de incluir la unidad de tiempo es lo que activa la animación suave.
Qué ventajas tiene usar clases dinámicas frente a renderizado condicional
La diferencia entre ambos enfoques se nota apenas pruebas el formulario.
- El elemento permanece en el DOM, así que los inputs vecinos no se mueven.
- La animación de
opacity da una transición visual mucho más limpia.
- Puedes inspeccionar el HTML y ver cómo la clase
show se agrega y quita dinámicamente según la validación.
- Es una buena práctica de usabilidad: el usuario no pierde el contexto visual mientras escribe.
¿Cuándo usar class binding y cuándo ngIf? Usa class binding cuando solo cambia el estilo o visibilidad de un elemento que debe permanecer en el layout. Usa *ngIf cuando el elemento realmente no debe existir en ciertos estados, como bloques de contenido completos.
Cómo aplicar este patrón a una lista de tareas
El mismo principio sirve para reflejar el estado de una tarea. Si tienes una lista y cada item tiene un estado completed, puedes activar una clase visual condicional:
html
<li [class.completed]="task.completed">{{ task.title }}</li>
Cuando task.completed sea true, la clase completed se aplica y puedes definir en CSS un estilo como text-decoration: line-through o un color atenuado. Lo mismo aplica para un estado de edición: si el usuario empieza a editar, activas otra clase dinámica que cambie la apariencia del item.
Este patrón mantiene tu HTML declarativo y tu CSS responsable de la presentación, sin lógica imperativa para agregar o quitar clases manualmente.
¿Cómo resolviste el reto del estado completed en tu lista de tareas? Cuéntalo en los comentarios.