Application Framework

Angular

Angular es el framework "batteries-included": prioriza TypeScript, incluye inyección de dependencias integrada y posee una estructura definida que escala desde una aplicación pequeña hasta una base de código empresarial masiva.

intermediate16 min readUpdated 15 sept 2026
counter.component.ts
ts
// counter.component.ts
import { Component, signal } from "@angular/core";

@Component({
  selector: "app-counter",
  standalone: true,
  template: `
    <button (click)="increment()">
      Clicked {{ count() }} times
    </button>
  `,
})
export class CounterComponent {
  count = signal(0);

  increment() {
    this.count.update((c) => c + 1);
  }
}
Mantenido por
Google
Lenguaje
TypeScript first
Versión mayor actual
Angular 17+
Reactividad
Signals y RxJS
DI
Integrada en el framework
Alcance
Plataforma de aplicación completa

Por que importa

Por qué las empresas eligen Angular

Batteries included

El enrutamiento, los formularios, HTTP, las pruebas y el tooling vienen integrados, evitando que los equipos tengan que armar un stack con una docena de paquetes inconexos.

Estructura definida

Las convenciones y la inyección de dependencias mantienen la consistencia en bases de código grandes, algo fundamental cuando muchos desarrolladores comparten un repositorio.

Diseñado para escalar

El tipado fuerte, una CLI potente y una configuración de pruebas desde el primer día hacen de Angular la elección común para aplicaciones empresariales de larga duración.

La imagen completa

Las tres ideas detrás de Angular

Un árbol de componentes, inyección de dependencias y una capa reactiva. Angular integra las tres como un sistema coherente y estructurado.

Components

UI

Clases decoradas con @Component que vinculan una plantilla con lógica y estilos.

Dependency injection

Wiring

Un contenedor de primer nivel que provee e inyecta servicios en toda la aplicación.

Reactivity

Change

Signals para el estado local y observables de RxJS para flujos de datos, impulsando la detección de cambios.

Angular de un vistazo

El núcleo de Angular

Components

Una clase de TypeScript, una plantilla HTML y estilos, conectados mediante un decorador.

Templates & binding

La interpolación, el property binding y el event binding conectan la clase con la vista.

Signals

Valores reactivos de grano fino que actualizan la vista sin necesidad de una comprobación completa.

RxJS

Observables y operadores para manejar flujos asíncronos de eventos.

Services & DI

Comparte lógica y datos a través de servicios inyectables en lugar de importar globales.

Router

Configura rutas, guards y áreas de funcionalidades con lazy-loading de forma declarativa.

Una breve historia

De AngularJS a una plataforma moderna

  1. 2010

    AngularJS

    El framework original populariza el two-way binding y las aplicaciones de una sola página (SPA).

    10
  2. 2016

    Reescritura de Angular 2

    Una reescritura total basada en componentes, TypeScript y un nuevo sistema de inyección de dependencias.

    16
  3. 2020

    Ivy y modo estricto

    Un nuevo compilador mejora el tamaño del bundle y permite una comprobación de tipos más estricta.

    20
  4. 2023

    Signals y standalone

    Llegan los Signals y los standalone components se convierten en la opción recomendada por defecto.

    23
  5. Today

    Una plataforma moderna

    La carga diferida (deferred loading), la detección de cambios zoneless y una CLI unificada mantienen a Angular competitivo.

    Today

La guia completa

Angular: Todo lo que necesitas saber

¿Qué es Angular?

Angular es un framework de aplicaciones completo mantenido por Google. Mientras que React es una librería alrededor de la cual ensamblas un stack, Angular ya incluye el stack: componentes, routing, formularios, HTTP, inyección de dependencias, testing y una potente CLI, todo diseñado para trabajar en conjunto. Está centrado en TypeScript y es opinionated, que es precisamente la razón por la cual los equipos grandes lo eligen.

Esa completitud es la principal contrapartida. Aceptas una curva de aprendizaje más pronunciada y más convenciones del framework a cambio de consistencia, herramientas sólidas y menos decisiones arquitectónicas que tomar desde cero. Para un prototipo pequeño, esto puede sentirse pesado; para una base de código empresarial de cinco años, suele ser un alivio.

Componentes y plantillas

Un componente es una clase de TypeScript decorada con @Component, vinculada a una plantilla HTML y estilos opcionales.

// user-card.component.ts
import { Component, Input } from "@angular/core";

@Component({
  selector: "app-user-card",
  standalone: true,
  template: `
    <article class="card">
      <h3>{{ user.name }}</h3>
      <p>{{ user.email }}</p>
    </article>
  `,
})
export class UserCardComponent {
  @Input({ required: true }) user!: { name: string; email: string };
}

La plantilla utiliza {{ }} para la interpolación y directivas para la lógica. El Angular moderno utiliza bloques de flujo de control integrados en lugar de las antiguas directivas estructurales.

<!-- list.html -->
@if (users.length > 0) {
  <ul>
    @for (user of users; track user.id) {
      <li>{{ user.name }}</li>
    }
  </ul>
} @else {
  <p>No users yet.</p>
}

La expresión track en @for cumple la misma función que una key en React o Vue: le indica a Angular cómo emparejar los elementos entre actualizaciones.

Data binding

Las plantillas de Angular admiten cuatro tipos de binding.

  • Interpolation {{ value }} renderiza un valor como texto.
  • Property binding [src]="url" asigna una propiedad de un elemento a partir de una expresión.
  • Event binding (click)="save()" llama a un método cuando se dispara un evento.
  • Two-way binding [(ngModel)]="name" combina ambos para los inputs de formularios.
<!-- bindings.html -->
<img [src]="user.avatar" [alt]="user.name" />
<button (click)="save()">Save</button>
<input [(ngModel)]="query" />

El two-way binding es conveniente para formularios sencillos, pero para cualquier cosa que requiera validación, los reactive forms suelen ser una mejor opción.

Signals

Los Signals son la primitiva de reactividad moderna de Angular. Un signal contiene un valor y notifica a los consumidores interesados cuando este cambia, lo que permite que el framework actualice únicamente las partes de la vista que dependen de él.

// cart.component.ts
import { Component, signal, computed } from "@angular/core";

@Component({
  selector: "app-cart",
  standalone: true,
  template: `<p>Total: {{ total() }}</p>`,
})
export class CartComponent {
  items = signal([{ price: 10 }, { price: 20 }]);

  total = computed(() =>
    this.items().reduce((sum, i) => sum + i.price, 0),
  );

  add(price: number) {
    this.items.update((items) => [...items, { price }]);
  }
}

computed deriva un valor de otros signals y lo almacena en caché hasta que una dependencia cambia. effect ejecuta un efecto secundario cuando cambian los signals que lee. Juntos, cubren la mayor parte de las necesidades de los componentes.

RxJS y observables

Angular tiene una integración profunda con RxJS. Un observable representa un flujo de valores a lo largo del tiempo, y los operadores permiten transformar y combinar dichos flujos.

// search.component.ts
import { Component } from "@angular/core";
import { toSignal } from "@angular/core/rxjs-interop";
import { debounceTime, distinctUntilChanged, switchMap } from "rxjs";

@Component({ /* ... */ })
export class SearchComponent {
  private query$ = new Subject<string>();

  results = toSignal(
    this.query$.pipe(
      debounceTime(300),
      distinctUntilChanged(),
      switchMap((q) => this.api.search(q)),
    ),
    { initialValue: [] },
  );
}

Aquí es donde RxJS demuestra su valor: el debouncing, la cancelación de peticiones obsoletas y la combinación de flujos son difíciles de expresar con promesas simples. Para estados sincrónicos sencillos, los signals son más simples. El Angular moderno permite mezclar ambos y convertirlos mediante toSignal y toObservable.

Servicios e inyección de dependencias

La lógica y los datos compartidos pertenecen a los servicios, no a los componentes. La inyección de dependencias los suministra donde sea necesario.

// users.service.ts
import { Injectable, inject } from "@angular/core";
import { HttpClient } from "@angular/common/http";

@Injectable({ providedIn: "root" })
export class UsersService {
  private http = inject(HttpClient);

  getAll() {
    return this.http.get<User[]>("/api/users");
  }
}
// users.component.ts
export class UsersComponent {
  private users = inject(UsersService);
  list = toSignal(this.users.getAll(), { initialValue: [] });
}

providedIn: "root" registra un singleton para toda la aplicación. La DI facilita el intercambio de servicios en las pruebas y mantiene los componentes enfocados en la presentación.

Routing

El Router de Angular mapea URLs a componentes y soporta rutas anidadas, guards, resolvers y lazy loading.

// app.routes.ts
import { Routes } from "@angular/router";

export const routes: Routes = [
  { path: "", component: HomeComponent },
  { path: "users/:id", component: UserProfileComponent },
  {
    path: "admin",
    loadChildren: () => import("./admin/admin.routes").then((m) => m.ADMIN_ROUTES),
  },
];

La funcionalidad de lazy loading mantiene el bundle inicial pequeño, y los guards te permiten bloquear la navegación hasta que se cumpla una condición, como la autenticación.

Formularios y HTTP

Angular tiene dos enfoques para manejar formularios. Los Reactive forms definen el modelo y los validadores en la clase, lo que permite escalar mejor y facilita las pruebas. Los Template-driven forms utilizan directivas como ngModel y son más rápidos para casos sencillos.

// signup.component.ts
form = new FormGroup({
  email: new FormControl("", [Validators.required, Validators.email]),
  password: new FormControl("", [Validators.required, Validators.minLength(8)]),
});

submit() {
  if (this.form.invalid) return;
  this.http.post("/api/signup", this.form.getRawValue()).subscribe();
}

HttpClient devuelve observables, por lo que las peticiones se pueden componer con operadores de RxJS para gestionar reintentos, cancelaciones y el manejo de errores.

Mejores prácticas

  • Prioriza el uso de standalone components y signals para el código nuevo.
  • Mantén los componentes enfocados en la presentación y traslada la lógica a los servicios.
  • Utiliza reactive forms para cualquier funcionalidad que requiera validación o campos dinámicos.
  • Implementa lazy-load en las áreas de funcionalidades para mantener el bundle inicial reducido.
  • Utiliza la detección de cambios OnPush o signals para limitar las comprobaciones innecesarias.
  • Rastrea los elementos en @for mediante un valor único y estable.
  • Cancela la suscripción a los observables de larga duración, o utiliza el async pipe y toSignal.

Errores comunes

  • Colocar la lógica de negocio en los componentes en lugar de en los servicios.
  • Suscribirse manualmente y olvidar cancelar la suscripción, lo que provoca fugas de memoria.
  • Recurrir a RxJS cuando un signal sería más sencillo.
  • Mutar el valor de un signal directamente en lugar de usar set o update.
  • Crear un único NgModule enorme en lugar de rutas de funcionalidades con lazy-loading.
  • Tratar a Angular como si fuera React y luchar contra la estructura del framework.

Próximos pasos

Angular recompensa la paciencia con una estructura que se mantiene sólida a lo largo de los años. Profundiza en TypeScript, comprende cómo se compara con React y Vue, y aprende sobre las herramientas de Node.js que impulsan su CLI. Después, construye una funcionalidad que incluya routing, un servicio y un formulario reactivo para ver cómo encajan todas las piezas.

Estado local

Los Signals son el estándar moderno para el estado síncrono de los componentes. Usa RxJS cuando realmente tengas un flujo de datos (stream).

Preferir
const count = signal(0);
count.update((c) => c + 1);
// read it in the template
// {{ count() }}
Evitar
count$ = new BehaviorSubject(0);
count$.next(
  this.count$.value + 1,
);
// needs an async pipe

Creación de formularios

Los formularios reactivos mantienen el modelo en la clase, lo que escala mejor para validaciones y campos dinámicos.

Reactive
form = new FormGroup({
  email: new FormControl("", [
    Validators.required,
    Validators.email,
  ]),
});
Template-driven
<form #f="ngForm">
  <input
    name="email"
    ngModel
    required
    email
  />
</form>

Preguntas frecuentes

Preguntas frecuentes

Keep learning

Related topics from the roadmap.

$ comienza a aprender

Listo para aprender Angular?

Nuestro tutorial interactivo te guia a traves de Angular paso a paso — con quizzes y codigo real que puedes ejecutar en el navegador.