El enrutamiento
Introducción
En este capítulo, se va a abordar la navegación dentro de una aplicación. Para esto, se van a describir las nociones de ruta y navegación. Para ir más lejos en los detalles del enrutamiento con Angular, también se estudiarán las nociones de Resolver y de nombrados outlets.
Definir las rutas de una aplicación
La navegación dentro de una aplicación Angular se realiza gracias a un sistema de ruta, que se debe definir. Una ruta en su forma más básica es la asociación de un componente y de una URL. Cuando se pide esta URL, el módulo de enrutamiento realiza el renderizado del componente asociado.
Para realizar esta asociación de una URL a un componente, hay que definir una variable de tipo Routes. Este tipo se declara como una tabla para la que cada elemento es un objeto de tipo Route.
Por lo tanto, una ruta se compone de un atributo path que representa la URL (relativa o absoluta), asociada a esta ruta y un atributo component que es el componente a cargar cuando se llama a esta ruta.
import { Routes } from '@angular/Router';
import { ManzanaListComponent } from './manzana-list/manzana-
list.component';
export const ROUTES: Routes = [
{ path: 'manzanas', component: ManzanaListComponent }
];
En el ejemplo anterior, se ha declarado una ruta para que, cuando se llame a la URL ’manzanas’, se cargue el componente ManzanaListComponent. Sin embargo, es necesario guardar esta ruta con el objetivo de que sea utilizable.
También es posible realizar redirecciones. Es muy útil para definir rutas por defecto, por ejemplo. Para esto, en lugar...
El renderizado de componentes
Con el objetivo de que el enrutador pueda realizar el renderizado del componente, en primer lugar hay que guardar las rutas declaradas en la tabla ROUTES.
Esto se hace a nivel de la declaración del módulo de la aplicación. Para ello es necesario añadir a la aplicación el módulo de enrutamiento RouterModule. Este módulo se debe importar usando el método forRoot que expone. Este método toma como argumento un objeto de tipo Routes. Por lo tanto, es necesario pasarle la tabla de rutas definida anteriormente.
import { RouterModule } from '@angular/Router';
import { ROUTES } from './app.routes';
import ...
@NgModule({
declarations: [
...
],
imports: [
BrowserModule,
RouterModule.forRoot(ROUTES)
],
providers: [...],
bootstrap: [...]
})
export class AppModule { }
En el ejemplo de declaración de módulo anterior, la importación del módulo RouterModule se hace usando un objeto de tipo Routes, que viene del archivo app.routes.ts. Este archivo contiene el código del ejemplo anterior. Es una buena práctica definir las rutas en un archivo...
Navegar en su aplicación
Con el objetivo de navegar en una aplicación usando el módulo de enrutamiento, hay dos soluciones. En primer lugar, es posible navegar usando enlaces de hipertexto HTML (etiqueta «a»). Para hacer esto, hay que utilizar la directiva RouterLink.
Para el caso de las URL no dinámicas, es suficiente con asignar a esta directiva el valor de la propiedad path de la ruta asociada. Por ejemplo, <a RouterLink="/manzanas"> apuntará a la ruta manzanas definida en la tabla de rutas.
Para el caso de URL dinámicas, esta directiva recibe como argumento una tabla de valores. Estos valores se corresponden con la ruta apuntada por este enlace. Por ejemplo, para navegar a la página de detalle de una de las variedades de manzana del ejemplo anterior, es posible utilizar la sintaxis siguiente:
<ul>
<li *ngFor="let manzana of manzanas">
{{manzana.id}}
<a [RouterLink]="['/manzana', manzana.id]">{{manzana.name}}</a>
</li>
</ul>
El enlace anterior apuntará a la página de detalle de una variedad de manzana, y la parte dinámica de la ruta se rellenará con el identificador de la variedad de manzanas en la que ha pulsado el usuario.
También es posible utilizar el atributo...
Recuperación de los datos de enrutamiento
Con el objetivo de obtener información relativa a la ruta activa dentro del componente, hay que inyectar el objeto ActivatedRoute. Este objeto contiene principalmente la información de los argumentos que se pasan a la ruta durante la navegación.
Para recuperar esta información, es posible pasar por la propiedad snapshot de este objeto. Esta propiedad contiene a su vez una propiedad params, que contiene todos los argumentos que se pasan a la ruta durante la navegación.
Import ...
import { ActivatedRoute, Router } from '@angular/Router';
@Component({...})
export class ManzanaDetailsComponent implements OnInit {
manzana: Manzana;
constructor(private manzanaService: ManzanaService,
private ruta: ActivatedRoute,
private Router: Router) { }
ngOnInit() {
const id = +this.ruta.snapshot.params['id'];
this.manzanaService.getManzana(id)
.subscribe(manzana => this.manzana = manzana);
}
goBack() { ...
Outlet con nombre
1. Definir outlets con nombre
El módulo de enrutamiento de Angular permite disponer de varios outlets dentro de un mismo componente (recuerde, un outlet es una instancia de la directiva RouterOutlet y permite especificarle al módulo de enrutamiento dónde debe representar el componente asociado a la ruta). Gracias a esta funcionalidad, es posible representar varias rutas al mismo tiempo, de manera totalmente independiente en una misma vista. Este mecanismo se puede utilizar con el objetivo de crear un layout de aplicación. Con una vista para el menú, otra para el cuerpo de la aplicación, otro para el encabezado, etc.
Por lo tanto, para utilizar esta funcionalidad es necesario poder diferenciar los outlets. Para esto, hay que utilizar el atributo name de la directiva RouterOutlet. Por ejemplo, para un outlet llamado list y un outlet llamado detail, las etiquetas se convierten en:
<Router-outlet name="list"></Router-outlet>
<Router-outlet name="detail"></Router-outlet>
También hay que definir las rutas que usa este mecanismo. Para esto, hay que utilizar la propiedad outlet de los objetos Route, que se registran en la aplicación. Esta propiedad se debe rellenar con el valor utilizado en el atributo name de la directiva RouterOutlet.
export const ROUTES: Routes = [
{
path: 'manzanas/:page', ...
Resolver
El módulo de enrutamiento de Angular permite pasar datos a la vista mediante dos mecanismos. El primero afecta a los datos estáticos. Para añadir datos estáticos a una vista, es suficiente con añadir una propiedad data durante la creación de la ruta:
export const ROUTES: Routes = [
{
path: '',
redirectTo: '/(list:manzanas/0)',
pathMatch: 'full'
},
{
path: 'manzanas/:page',
component: ManzanaListComponent,
outlet: 'list'
},
{
path: 'manzana/:id',
component: ManzanaDetailsComponent,
outlet: 'detail',
data: {
manzana: new Manzana(12, 'staticManzana', true, true, true)
}
}
];
En el ejemplo anterior, en la última ruta, se ha añadida la propiedad data a la definición de la ruta. Por lo tanto, ahora hay disponible un objeto Manzana en las propiedades de la ruta que se pasa al componente. Por el contrario, esta nunca se modificará, independientemente del valor...