¿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