Angular

¿Qué hay detrás de Angular?

Angular es un framework para construir aplicaciones web con TypeScript. Permite dividir la interfaz en componentes, gestionar datos, consumir APIs y navegar entre pantallas sin recargar el navegador.

Para entender cómo funciona, conviene separar varios conceptos que trabajan juntos. Estos son quince pilares que ayudan a construir una visión general de Angular.

1. Estructura Modular (Standalone)

Antes, toda aplicación Angular dependía de un NgModule (AppModule): un bloque que declaraba a qué componentes, directivas y servicios pertenecía cada pieza.

Desde Angular 14+, la forma recomendada es la arquitectura standalone: cada componente importa de forma directa únicamente lo que usa, sin necesidad de un módulo contenedor.

import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-inicio',
  imports: [CommonModule],
  template: `<p>Hola</p>`,
  standalone: true,
})
export class InicioComponent {}

Cada pieza declara sus propias dependencias y la aplicación resulta más simple de entender y mantener.

2. Componentes (Clase + HTML + CSS)

Un componente es una pieza reutilizable que combina tres partes: la clase (datos y lógica), el template (HTML que define lo que se ve) y los estilos (CSS que define cómo se ve).

@Component({
  selector: 'app-tarjeta',
  templateUrl: './tarjeta.component.html',
  styleUrl: './tarjeta.component.css',
})
export class TarjetaComponent {
  nombre = 'Arturo';
}
<div class="tarjeta">
  <h3>{{ nombre }}</h3>
</div>

La clase mantiene el estado y el template lo dibuja. El CSS se aísla para no afectar a otros componentes.

3. Interpolación {{ }}

La interpolación permite volcar datos de la clase directamente en el template utilizando dobles llaves.

export class UsuarioComponent {
  nombre = 'María';
}
<p>Hola, {{ nombre }}</p>

Cuando el valor cambia en la clase, Angular re-renderiza automáticamente la parte afectada del template. No hace falta actualizar el DOM a mano.

4. Property Binding [prop]

El property binding envía valores de la clase hacia propiedades de elementos HTML o hacia inputs de otros componentes.

export class BotonComponent {
  deshabilitado = true;
}
<button [disabled]="deshabilitado">Guardar</button>

Los corchetes indican que el valor se evalúa como expresión de TypeScript, no como texto literal.

5. Event Binding (evento)

El event binding reacciona a eventos del usuario como clics, teclas o cambios de foco.

<button (click)="guardar()">Guardar</button>
<input (keyup.enter)="buscar()">
export class FormularioComponent {
  guardar() { /* ... */ }
  buscar() { /* ... */ }
}

Los paréntesis indican el evento y la cadena a la derecha es el método de la clase que se ejecuta.

6. Two-Way Binding [(ngModel)]

La sintaxis banana-in-a-box [(ngModel)] combina property binding y event binding para lograr una sincronía bidireccional entre la clase y un input.

export class BuscadorComponent {
  termino = '';
}
<input [(ngModel)]="termino">
<p>Buscando: {{ termino }}</p>

Lo que escribes en el input se guarda en la clase y lo que cambia la clase también se refleja en el input. Para usarlo debe importarse FormsModule.

7. Directivas @if / @for

Las directivas de control crean o destruyen el DOM según condiciones y listados.

@if (usuario) {
  <p>Bienvenido, {{ usuario }}</p>
} @else {
  <p>Inicia sesión</p>
}

@for (tarea of tareas; track tarea.id) {
  <li>{{ tarea.nombre }}</li>
}

@if decide qué parte del DOM existe y @for repite un bloque por cada elemento de una lista, de forma legible y performante.

8. ngClass / ngStyle

ngClass y ngStyle aplican clases o estilos de forma dinámica según condiciones.

<div [ngClass]="{ 'activo': seleccionado, 'inactivo': !seleccionado }"></div>
<div [ngStyle]="{ color: error ? 'red' : 'green' }"></div>

Esto permite que una misma plantilla cambie su apariencia sin escribir lógica de manipulación del DOM.

9. Inyección de Dependencias inject()

Angular gestiona las dependencias y permite pedirlas con una sola línea mediante la función inject().

import { inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';

export class ProductosService {
  private http = inject(HttpClient);
}

Ya no hace falta escribir un constructor verboso ni que las clases estén decoradas para recibir sus dependencias.

10. Servicios @Injectable

Un servicio concentra datos y lógica compartidos. Con providedIn: 'root' se registra como singleton global: una sola instancia para toda la aplicación.

import { Injectable } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class CarritoService {
  private items: string[] = [];

  agregar(item: string) {
    this.items.push(item);
  }
}

Cualquier componente puede inyectarlo y compartir el mismo estado de items en toda la aplicación.

11. HttpClient + Observables

HttpClient permite consumir APIs REST devolviendo Observables, la primitiva reactiva de RxJS.

import { inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';

export class ProductosService {
  private http = inject(HttpClient);

  obtener() {
    return this.http.get('https://api.ejemplo.com/productos');
  }
}
export class ProductosComponent {
  private servicio = inject(ProductosService);

  ngOnInit() {
    this.servicio.obtener().subscribe({
      next: (data) => console.log(data),
      error: (err) => console.error(err),
    });
  }
}

El componente se suscribe al flujo de datos y decide qué hacer cuando llega la respuesta o cuando ocurre un error.

12. Enrutamiento Router / SPA

El router permite navegar entre páginas sin recargar el navegador, manteniendo la experiencia de una SPA.

export const routes: Routes = [
  { path: '', component: InicioComponent },
  { path: 'productos', component: ProductosComponent },
];
<a routerLink="/productos">Productos</a>
<router-outlet></router-outlet>

routerLink cambia la URL sin recargar y <router-outlet> dibuja el componente de la ruta activa.

13. Rutas Protegidas (Guards)

Un guard decide si una ruta puede activarse antes de que cargue, permitiendo bloquear el acceso o redirigir.

import { inject } from '@angular/core';
import { CanActivateFn, Router } from '@angular/router';

export const authGuard: CanActivateFn = () => {
  const auth = inject(AuthService);
  const router = inject(Router);

  return auth.estaLogueado() ? true : router.createUrlTree(['/ingresar']);
};

Al configurarlo en una ruta, Angular ejecuta el guard antes de navegar: si devuelve false o una nueva URL, el acceso se bloquea o se redirige.

14. Formularios Reactivos

Los formularios reactivos modelan el formulario y sus validaciones desde la clase, con control total sobre los valores y su estado.

import { inject } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';

export class RegistroComponent {
  private fb = inject(FormBuilder);

  form = this.fb.nonNullable.group({
    nombre: ['', [Validators.required, Validators.minLength(3)]],
    correo: ['', [Validators.required, Validators.email]],
  });
}
<form [formGroup]="form" (ngSubmit)="enviar()">
  <input formControlName="nombre">
  <input formControlName="correo">
</form>

Los FormControl y FormGroup permiten validar, limpiar y observar los valores de forma programática.

15. Pipes de Transformación |

Los pipes formatean valores al momento de pintarlos, con una simple sintaxis |.

<p>{{ precio | currency: 'USD' }}</p>
<p>{{ fecha | date: 'yyyy-MM-dd' }}</p>
<p>{{ texto | uppercase }}</p>

Angular incluye pipes para moneda, fechas, texto, números y más. También pueden crearse pipes personalizados para formatos propios.

Consideraciones

Angular se apoya en una base sólida de conceptos que trabajan juntos: componentes que separan datos de interfaz, enlaces que sincronizan clase y template, directivas que controlan el DOM, servicios e inyección de dependencias que organizan la lógica, y herramientas como el enrutamiento, los guards, los formularios reactivos y los pipes que resuelven problemas concretos de la aplicación.

Dominar estos quince pilares permite construir aplicaciones web estructuradas, reactivas y mantenibles sin depender de recargar la página ni de manipular el DOM manualmente.

© Arturo Juárez Monroy