Sintaxis @switch y @case
La directiva @switch representa la evolución moderna del renderizado condicional múltiple en Angular. Esta sintaxis, introducida en Angular 17 y estabilizada desde Angular 18, reemplaza completamente la antigua directiva *ngSwitch
ofreciendo un enfoque más limpio y eficiente.
La estructura básica de @switch sigue un patrón familiar para quienes conocen las declaraciones switch de JavaScript o TypeScript, pero adaptado específicamente para templates de Angular:
@switch (expresion) {
@case (valor1) {
<!-- Contenido cuando expresion === valor1 -->
}
@case (valor2) {
<!-- Contenido cuando expresion === valor2 -->
}
@default {
<!-- Contenido por defecto -->
}
}
Anatomía de la sintaxis
La directiva @switch evalúa una expresión y renderiza el contenido del @case
correspondiente que coincida con el valor. Cada caso debe contener un valor único y específico para la comparación.
Veamos un ejemplo práctico con el estado de un pedido:
@switch (estadoPedido) {
@case ('pendiente') {
<div class="estado-pendiente">
<p>Tu pedido está pendiente de procesamiento</p>
<span class="icono">⏳</span>
</div>
}
@case ('enviado') {
<div class="estado-enviado">
<p>Tu pedido ha sido enviado</p>
<span class="icono">🚚</span>
</div>
}
@case ('entregado') {
<div class="estado-entregado">
<p>Tu pedido ha sido entregado</p>
<span class="icono">✅</span>
</div>
}
@default {
<div class="estado-desconocido">
<p>Estado del pedido no disponible</p>
</div>
}
}
Bloque @default
El bloque @default actúa como el caso por defecto cuando ninguno de los @case
coincide con la expresión evaluada. Su uso es opcional, pero recomendado para manejar valores inesperados:
@switch (tipoUsuario) {
@case ('admin') {
<button class="btn-admin">Panel de Administración</button>
}
@case ('editor') {
<button class="btn-editor">Crear Contenido</button>
}
@case ('viewer') {
<button class="btn-viewer">Ver Contenido</button>
}
@default {
<p>Tipo de usuario no reconocido</p>
}
}
Comparación por identidad estricta
La directiva @switch utiliza comparación por identidad estricta (===
), lo que significa que tanto el valor como el tipo deben coincidir exactamente. Esto es importante cuando trabajamos con diferentes tipos de datos:
<!-- En el componente -->
export class MiComponente {
numero = 1;
texto = '1';
}
<!-- En el template -->
@switch (numero) {
@case (1) {
<p>Número uno</p> <!-- ✅ Se renderiza -->
}
@case ('1') {
<p>String uno</p> <!-- ❌ No se renderiza -->
}
}
Sintaxis con expresiones del componente
Los casos pueden utilizar propiedades del componente para realizar comparaciones dinámicas:
export class ComponenteEstados {
ESTADO_ACTIVO = 'activo';
ESTADO_INACTIVO = 'inactivo';
ESTADO_PENDIENTE = 'pendiente';
estadoActual = 'activo';
}
@switch (estadoActual) {
@case (ESTADO_ACTIVO) {
<div class="badge-activo">Activo</div>
}
@case (ESTADO_INACTIVO) {
<div class="badge-inactivo">Inactivo</div>
}
@case (ESTADO_PENDIENTE) {
<div class="badge-pendiente">Pendiente</div>
}
}
Ventajas sobre la sintaxis anterior
La nueva sintaxis @switch ofrece varias mejoras significativas respecto a *ngSwitch
:
- Mayor legibilidad: La estructura es más clara y fácil de seguir
- Mejor rendimiento: Optimizaciones internas del compilador de Angular
- Sintaxis más natural: Similar a las declaraciones switch de TypeScript
- Menos verbosidad: No requiere directivas adicionales como
*ngSwitchCase
La migración desde *ngSwitch
es directa, pero la nueva sintaxis representa una mejora sustancial en la experiencia de desarrollo y el rendimiento de la aplicación.
Comparaciones múltiples
La directiva @switch demuestra su verdadero valor cuando necesitamos manejar diferentes tipos de datos y múltiples condiciones de forma eficiente. A diferencia de las cadenas de @if
consecutivos, @switch
ofrece una solución más limpia y optimizada para escenarios con múltiples comparaciones.
Trabajando con diferentes tipos de datos
Una de las ventajas de @switch es su capacidad para manejar distintos tipos de datos de manera consistente. Veamos ejemplos prácticos con strings, números y enumeraciones:
Ejemplo con strings - Sistema de roles:
export class UsuarioComponent {
rolUsuario: string = 'moderador';
}
@switch (rolUsuario) {
@case ('admin') {
<div class="panel-admin">
<h3>Panel de Administración</h3>
<button>Gestionar usuarios</button>
<button>Configuración del sistema</button>
</div>
}
@case ('moderador') {
<div class="panel-moderador">
<h3>Panel de Moderación</h3>
<button>Revisar contenido</button>
<button>Gestionar comentarios</button>
</div>
}
@case ('usuario') {
<div class="panel-usuario">
<h3>Mi perfil</h3>
<button>Editar datos</button>
</div>
}
@default {
<div class="acceso-denegado">
<p>Rol no reconocido</p>
</div>
}
}
Ejemplo con números - Niveles de experiencia:
export class JuegoComponent {
nivelJugador: number = 25;
}
@switch (Math.floor(nivelJugador / 10)) {
@case (0) {
<div class="nivel-principiante">
<span class="badge">Principiante</span>
<p>Nivel 1-9: ¡Sigue practicando!</p>
</div>
}
@case (1) {
<div class="nivel-intermedio">
<span class="badge">Intermedio</span>
<p>Nivel 10-19: Buen progreso</p>
</div>
}
@case (2) {
<div class="nivel-avanzado">
<span class="badge">Avanzado</span>
<p>Nivel 20-29: ¡Excelente!</p>
</div>
}
@default {
<div class="nivel-experto">
<span class="badge">Experto</span>
<p>Nivel 30+: ¡Eres un maestro!</p>
</div>
}
}
Uso con enumeraciones TypeScript
Los enums son especialmente útiles con @switch
porque proporcionan type safety y mejor mantenibilidad del código:
export enum EstadoConexion {
DESCONECTADO = 'desconectado',
CONECTANDO = 'conectando',
CONECTADO = 'conectado',
ERROR = 'error'
}
export class ConexionComponent {
estado = EstadoConexion.CONECTANDO;
}
@switch (estado) {
@case (EstadoConexion.DESCONECTADO) {
<div class="estado-offline">
<span class="indicador rojo"></span>
<p>Sin conexión</p>
<button (click)="conectar()">Conectar</button>
</div>
}
@case (EstadoConexion.CONECTANDO) {
<div class="estado-conectando">
<span class="indicador amarillo pulsante"></span>
<p>Conectando...</p>
</div>
}
@case (EstadoConexion.CONECTADO) {
<div class="estado-online">
<span class="indicador verde"></span>
<p>Conectado exitosamente</p>
</div>
}
@case (EstadoConexion.ERROR) {
<div class="estado-error">
<span class="indicador rojo"></span>
<p>Error de conexión</p>
<button (click)="reintentar()">Reintentar</button>
</div>
}
}
Comparaciones con valores booleanos
Aunque menos común, @switch también puede manejar valores booleanos de forma efectiva:
export class NotificacionComponent {
notificacionesActivas = true;
modoOscuro = false;
}
@switch (notificacionesActivas) {
@case (true) {
<div class="notificaciones-on">
<p>Notificaciones activadas</p>
<span class="icono">🔔</span>
</div>
}
@case (false) {
<div class="notificaciones-off">
<p>Notificaciones desactivadas</p>
<span class="icono">🔕</span>
</div>
}
}
Cuándo usar @switch vs múltiples @if
La elección entre @switch y múltiples @if
depende del escenario específico:
Usa @switch cuando:
- Comparas una sola variable contra múltiples valores específicos
- Los valores son mutuamente excluyentes
- Tienes 3 o más condiciones relacionadas
- Necesitas un caso por defecto claro
Usa múltiples @if cuando:
- Comparas diferentes variables o expresiones complejas
- Las condiciones no son mutuamente excluyentes
- Necesitas lógica compleja en las condiciones
- Tienes pocas condiciones (1-2)
Ejemplo comparativo - Mejor con @switch:
<!-- ✅ Recomendado: @switch para una variable, múltiples valores -->
@switch (tipoAlerta) {
@case ('info') { <div class="alert-info">Información</div> }
@case ('warning') { <div class="alert-warning">Advertencia</div> }
@case ('error') { <div class="alert-error">Error</div> }
@case ('success') { <div class="alert-success">Éxito</div> }
}
<!-- ❌ Menos eficiente: múltiples @if para la misma variable -->
@if (tipoAlerta === 'info') {
<div class="alert-info">Información</div>
} @else if (tipoAlerta === 'warning') {
<div class="alert-warning">Advertencia</div>
} @else if (tipoAlerta === 'error') {
<div class="alert-error">Error</div>
} @else if (tipoAlerta === 'success') {
<div class="alert-success">Éxito</div>
}
Ejemplo comparativo - Mejor con @if:
<!-- ✅ Recomendado: @if para condiciones diferentes -->
@if (usuario.esAdmin && configuracion.mostrarPanel) {
<div>Panel de administración</div>
}
@if (notificaciones.nuevas > 0) {
<div>Tienes {{ notificaciones.nuevas }} mensajes</div>
}
@if (sesion.expiraSoon) {
<div>Tu sesión expirará pronto</div>
}
Optimización de rendimiento
Angular optimiza internamente las directivas @switch, realizando una sola evaluación de la expresión y comparándola eficientemente con todos los casos. Esto resulta en mejor rendimiento que múltiples evaluaciones @if
consecutivas para la misma variable.
La nueva sintaxis de control de flujo también permite al compilador de Angular generar código más eficiente, reduciendo el overhead en tiempo de ejecución y mejorando la experiencia del usuario final.
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 la sintaxis y estructura básica de la directiva @switch y @case en Angular.
- Aprender a utilizar el bloque @default para manejar casos no contemplados.
- Diferenciar cuándo usar @switch frente a múltiples directivas @if.
- Aplicar @switch con distintos tipos de datos, incluyendo strings, números y enums.
- Conocer las ventajas de rendimiento y legibilidad que ofrece la nueva sintaxis sobre *ngSwitch.