Existen ocasiones en donde necesitamos pasar un parámetro, generalmente un identificador, a una ruta con la intención de utilizarlo para llamar a una API y obtener cierta información. En esta ocasión vamos a ver cómo definir una ruta que acepta un parámetro, cómo utilizar la directiva routerLink
para pasar el valor del parámetro a través de la ruta y también cómo acceder al valor del parámetro desde un componente.
Crear un nuevo componente
En primer lugar vamos a crear un nuevo componente ejecutando el siguiente comando del Angular CLI:
ng generate component post
Definir la nueva ruta
Lo próximo a realizar es agregar una nueva ruta hacia nuestro nuevo componente en el array de definiciones de rutas dentro de app.module.ts
. Vamos a crear un nuevo objeto y esta vez en la propiedad path
necesitaremos agregar /:id
para indicar que la ruta espera recibir un parámetro llamado id
. La definición de las rutas quedará de la siguiente forma:
// src/app/app.module.ts
const routes: Route[] = [
{ path: "home", component: HomeComponent },
{ path: "posts", component: PostsComponent },
{ path: "posts/:id", component: PostComponent },
{ path: "**", redirectTo: "home" }
];
Si ejecutamos el comando ng serve
podremos navegar a nuestro nuevo componente modificando la URL de nuestro navegador a, por ejemplo, /posts/1
. De esta forma, el valor del parámetro id
será el que pasemos al final de la URL.
Enlazar con nuestra aplicación
Para navegar hacia el nuevo componente desde nuestra aplicación haremos uso de la directiva routerLink
y agregaremos algunos valores de parámetros para simular un listado de links de navegación dentro de nuestro PostsComponent
.
<!-- src/app/posts/posts.component.html -->
<ul>
<li><a [routerLink]="['/posts', 1]">Post 1</a></li>
<li><a [routerLink]="['/posts', 2]">Post 2</a></li>
<li><a [routerLink]="['/posts', 3]">Post 3</a></li>
</ul>
De esta manera le indicamos a Angular que queremos navegar a las rutas /posts/1
, /posts/2
o /posts/3
al hacer click en alguno de los links.
Obtener el valor del parámetro
Como hablamos al principio, es posible que querramos obtener cierta información utilizando el valor del parámetro id
por lo que vamos a analizar las alternativas que tenemos para lograrlo.
Hay dos maneras diferentes de obtener el valor del parámetro.
La primera es a través del snapshot de la ruta. El snapshot de la ruta nos provee de un objeto llamado paramMap que expone los métodos get
, getAll
y has
para interactuar con los parámetros de la ruta actual.
Para acceder al snapshot de la ruta es necesario inyectar en el componente la clase ActivatedRoute como se muestra a continuación:
// src/app/post/post.component.ts
import { Component, OnInit } from "@angular/core";
import { ActivatedRoute } from "@angular/router";
@Component({
selector: "app-post",
templateUrl: "./post.component.html",
styleUrls: ["./post.component.css"]
})
export class PostComponent implements OnInit {
id: string;
constructor(private route: ActivatedRoute) {}
ngOnInit() {
this.id = this.route.snapshot.paramMap.get("id");
}
}
Y, para simplificar el ejemplo, vamos a simplemente mostrar el valor en el html:
<!-- src/app/post/post.component.html -->
<p>
Post con id: {{ id }}
</p>
Haciendo click sobre cada link observaremos que la aplicación muestra correctamente el valor del parámetro. Sin embargo, esta alternativa para obtener el valor del identificador tiene una falencia ya que si la navegación a otros post se produce dentro de nuestro PostCompoent
, éste no detecta el cambio en el paramMap
por lo que no realiza la navegación.
Suscribir a los cambios en paramMap
Para solucionar el inconveniente antes mencionado debemos reemplazar el uso del snapshot de la ruta por una suscipción al parámetro paramMap
del ActivatedRoute
inyectado. De esta forma estaremos observando los cambios que suceden sobre los parámetros de la ruta y reaccionando correctamente ante cada uno de ellos.
El componente pasaría verse de la siguiente forma:
// src/app/post/post.component.ts
import { Component, OnInit } from "@angular/core";
import { ActivatedRoute, ParamMap } from "@angular/router";
@Component({
selector: "app-post",
templateUrl: "./post.component.html",
styleUrls: ["./post.component.css"]
})
export class PostComponent implements OnInit {
id: string;
constructor(private route: ActivatedRoute) {}
ngOnInit() {
this.route.paramMap.subscribe((params: ParamMap) => {
this.id = params.get('id');
});
}
}
Lo más importante a recordar a la hora de decidir entre cuáles de los métodos utilizar es saber en dónde sucede el cambio del parámetro.
Si el valor del parámetro es modificado dentro del mismo componente que lo utiliza entonces debemos suscribirnos al paramMap
.
En caso de que este no sea alterado dentro del componente podremos utilizar el snapshot de la ruta sin inconvenientes.
Aquí se puede ver el código final:
Top comments (0)