Angular 21 de Cero a Experto / Fundamentos
Control flow: @if, @for y @switch (adiós *ngIf)
Todo template real necesita decidir y repetir: "muestra esto SI hay gastos", "pinta una
tarjeta POR CADA gasto". En React esto lo hacías con JavaScript puro dentro de {}:
&&, ternarios y .map(). Angular tiene una sintaxis dedicada para el flujo de control
dentro del template, y en la versión 21 es completamente nueva: bloques @if, @for y
@switch. Si viste Angular antes, conocías *ngIf y *ngFor —hoy entiendes por qué los
reemplazaron y por qué el reemplazo es mucho mejor.
Decidir y repetir, dentro del HTML
@if / @else: el semáforo
@Component({
template: `
@if (gastos.length > 0) {
<ul>...la lista...</ul>
} @else if (cargando) {
<p>Cargando tus gastos…</p>
} @else {
<p>Aún no tienes gastos. ¡Agrega el primero!</p>
}
`,
})
export class ListaComponent {
gastos = [];
cargando = false;
}Compáralo con React: allá escribías {gastos.length > 0 ? <Lista/> : <Vacio/>} o
{cargando && <Spinner/>}. El @if de Angular hace lo mismo pero con @else if y @else
de verdad —nada de anidar ternarios ilegibles—. Se lee como un if normal de JavaScript,
porque en esencia lo es.
@for: la fotocopiadora (y por qué track es obligatorio)
@Component({
template: `
<ul>
@for (gasto of gastos; track gasto.id) {
<li>{{ gasto.nombre }} — {{ gasto.valor }} COP</li>
} @empty {
<li>No hay gastos para mostrar.</li>
}
</ul>
`,
})
export class ListaComponent {
gastos = [
{ id: 1, nombre: 'Café', valor: 4500 },
{ id: 2, nombre: 'Almuerzo', valor: 18000 },
];
}Tres cosas nuevas frente a React:
track gasto.ides OBLIGATORIO. Es exactamente el mismo concepto que lakeyde React: le dice a Angular cómo identificar cada elemento para actualizar el DOM de forma eficiente cuando la lista cambia. La diferencia es que Angular te OBLIGA a ponerlo (en React lakeyse podía olvidar y solo salía un warning). Usa siempre un id estable, nunca el índice —el mismo consejo que ya conoces—.@emptyes un bloque de regalo: qué mostrar cuando la lista está vacía. En React hacías eso con un@ifextra; aquí viene incluido.- Puedes pedir variables útiles del bucle:
@for (g of gastos; track g.id; let i = $index)te da el índice, y también existen$first,$last,$even,$odd,$count.
@switch: el clasificador
@Component({
template: `
@switch (gasto.categoria) {
@case ('comida') { <span>🍽️ Comida</span> }
@case ('transporte') { <span>🚌 Transporte</span> }
@case ('ocio') { <span>🎮 Ocio</span> }
@default { <span>📦 Otro</span> }
}
`,
})
export class EtiquetaComponent {
gasto = { categoria: 'comida' };
}Es el switch de JavaScript llevado al template. En React harías un objeto-mapa o una
cadena de ternarios; @switch lo expresa directo y legible.
Antes (*ngIf / *ngFor) vs Ahora (@if / @for)
¿Qué es `track gasto.id` en un bloque `@for` y por qué Angular lo exige?
Mini-reto
Escribe el template de un PanelGastosComponent que: 1) con @if, muestre "Cargando…" si
cargando es true, la lista si hay gastos, y un mensaje vacío si no; 2) con @for y
@empty, pinte un <li> por gasto usando track gasto.id; 3) con @switch, muestre un
ícono distinto según gasto.categoria. Luego reescribe mentalmente el @for como sería con
el viejo *ngFor y nota cuánto más código pedía.
Qué sigue
Tus componentes ya deciden y repiten, pero siguen aislados: no reciben datos de fuera ni
avisan de lo que pasa dentro. La próxima lección cierra el módulo con la comunicación entre
componentes al estilo moderno —input() y output()—, y verás cómo las señales entran en
escena por primera vez. El puente hacia el corazón de Angular 21.