CodeForge

Angular 21 de Cero a Experto / Fundamentos

Control flow: @if, @for y @switch (adiós *ngIf)

Teoría24 min20 XP

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

if.ts
@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)

for.ts
@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.id es OBLIGATORIO. Es exactamente el mismo concepto que la key de 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 la key se podía olvidar y solo salía un warning). Usa siempre un id estable, nunca el índice —el mismo consejo que ya conoces—.
  • @empty es un bloque de regalo: qué mostrar cuando la lista está vacía. En React hacías eso con un @if extra; 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

switch.ts
@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.