Saltar a contenido

7. Routing: navegación dentro de la SPA

La URL decide qué componente debe mostrarse.

URL                ROUTER                    VISTA ACTIVA
/students/42  →   coincide path + :id   →   StudentDetailComponent

Qué resuelve el Router

✅ Asocia URL y componente La ruta /students puede activar StudentListComponent
✅ Navega sin recargar Angular cambia el componente visible y conserva la aplicación cargada
✅ Admite parámetros /students/42 identifica un recurso mediante el parámetro :id
✅ Permite enlaces y navegación programática Se navega con routerLink o mediante el servicio Router

Configuración básica

① Definir las rutas

src/app/app.routes.ts
import { Routes } from '@angular/router';
import { StudentListComponent } from './students/student-list/student-list.component';
import { StudentDetailComponent } from './students/student-detail/student-detail.component';
import { StudentFormComponent } from './students/student-form/student-form.component';
import { NotFoundComponent } from './not-found/not-found.component';

export const routes: Routes = [
  { path: '', redirectTo: 'students', pathMatch: 'full' },
  { path: 'students', component: StudentListComponent },
  { path: 'students/new', component: StudentFormComponent },
  { path: 'students/:id', component: StudentDetailComponent },
  { path: '**', component: NotFoundComponent }
];
  • Las rutas se evalúan en orden; gana la primera que coincide. Por eso students/new va antes que students/:id (si no, new se tomaría como un id).
  • Las rutas se registran con provideRouter(routes) en app.config.ts.

② Reservar el punto de salida

<router-outlet /> indica dónde aparece el componente activado:

src/app/app.component.ts
import { Component } from '@angular/core';
import { RouterLink, RouterOutlet } from '@angular/router';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [RouterOutlet, RouterLink],
  template: `
    <nav>
      <a routerLink="/students">Estudiantes</a>
      <a routerLink="/students/new">Nuevo estudiante</a>
    </nav>

    <main>
      <router-outlet />
    </main>
  `
})
export class AppComponent {}

El menú permanece; solo cambia lo que hay dentro de <router-outlet>.

③ Crear enlaces internos

<a routerLink="/students">Estudiantes</a>
<a [routerLink]="['/students', student.id]">{{ student.name }}</a>

No uses href para navegar dentro de la app

<a href="/students"> pide la página completa al servidor y recarga la SPA, perdiendo el estado en memoria. Dentro de la aplicación usa routerLink.

④ Ruta comodín

** muestra una página 404 cuando ninguna ruta coincide. Siempre va al final de la lista.

Leer el parámetro :id

src/app/students/student-detail/student-detail.component.ts
import { Component, inject } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

@Component({
  selector: 'app-student-detail',
  standalone: true,
  template: `<h2>Estudiante {{ id }}</h2>`
})
export class StudentDetailComponent {
  private route = inject(ActivatedRoute);
  id = Number(this.route.snapshot.paramMap.get('id'));   // "/students/42" → 42
}

Los parámetros llegan como texto

/students/42 entrega "42"; se convierte con Number(...) antes de usarlo como identificador.

Para navegar desde el código —por ejemplo, después de guardar— se inyecta el servicio Router:

import { Router } from '@angular/router';

export class StudentListComponent {
  private router = inject(Router);

  goToDetail(id: number): void {
    this.router.navigate(['/students', id]);
  }
}

Mapa de la aplicación de ejemplo

flowchart LR
    U1["/students"] --> L[StudentListComponent]
    U2["/students/new"] --> F[StudentFormComponent]
    U3["/students/42"] --> D[StudentDetailComponent]
    U4["/cualquier-otra"] --> N[NotFoundComponent]
Despliegue: ¿por qué el servidor debe devolver index.html?

Las rutas existen solo en el navegador. Si alguien recarga /students/42, el servidor web no tiene ese archivo; debe responder index.html para que Angular arranque y resuelva la ruta. En nginx:

location / {
  try_files $uri $uri/ /index.html;
}

Siguiente: Formularios.