Parâmetros de Rotas em Angular
As rotas podem definir parâmetros que nos permitem passar dados para um componente a partir de fontes externas. Para ilustrar, vamos utilizar o projeto do tema anterior:
helloapp/ ├── src/ │ ├── app/ │ │ ├── about.component.ts │ │ ├── app.component.ts │ │ ├── app.config.ts │ │ ├── home.component.ts │ │ ├── not-found.component.ts │ ├── main.ts │ ├── index.html ├── angular.json ├── package-lock.json ├── package.json └── tsconfig.json
Dentro da pasta src/app
, vamos adicionar um novo arquivo item.component.ts
contendo o seguinte componente:
import { Component } from "@angular/core";
import { ActivatedRoute } from "@angular/router";
@Component({
selector: "item-info",
template: `<h2>Modelo {{ id }}</h2>`,
})
export class ItemComponent {
id: number;
constructor(private activateRoute: ActivatedRoute) {
this.id = activateRoute.snapshot.params["id"];
}
}
Para obter os parâmetros de rota, utilizamos o serviço ActivatedRoute
, que contém informações sobre a rota, incluindo os parâmetros e outras propriedades, como query strings. Esse serviço é injetado na aplicação através do mecanismo de dependency injection, permitindo que o recebamos diretamente no construtor do componente.
A propriedade snapshot
armazena o estado da rota e contém os parâmetros passados. Neste caso, esperamos que o parâmetro seja chamado "id", mas isso pode variar: o nome do parâmetro é flexível.
Agora precisamos definir uma rota que utilize este componente. Vamos modificar o arquivo app.config.ts
:
import { ApplicationConfig } from "@angular/core";
import { provideRouter, Routes } from "@angular/router";
import { HomeComponent } from "./home.component";
import { AboutComponent } from "./about.component";
import { NotFoundComponent } from "./not-found.component";
import { ItemComponent } from "./item.component";
const appRoutes: Routes = [
{ path: "", component: HomeComponent },
{ path: "about", component: AboutComponent },
{ path: "item/:id", component: ItemComponent },
{ path: "**", component: NotFoundComponent },
];
export const appConfig: ApplicationConfig = {
providers: [provideRouter(appRoutes)],
};
Aqui, adicionamos uma nova rota:
{ path: "item/:id", component: ItemComponent }
O token :id
representa o parâmetro da rota. Isso significa que podemos acessar o componente através de uma URL como /item/6
, onde o número 6 será passado como o parâmetro id
.
Agora, vamos ajustar o componente principal AppComponent
:
import { Component } from "@angular/core";
import { RouterOutlet, RouterLink } from "@angular/router";
@Component({
selector: "my-app",
standalone: true,
imports: [RouterOutlet, RouterLink],
styles: `
a {
padding: 5px;
}
`,
template: `<div>
<nav>
<a routerLink="">Home</a>
<a routerLink="/about">Sobre</a>
<a routerLink="/item/5">Item 5</a>
</nav>
<router-outlet></router-outlet>
</div>`,
})
export class AppComponent {}
Ao definir um link para um componente que utiliza parâmetros de rota, todos os parâmetros necessários são inseridos diretamente na URL:
<a routerLink="/item/5">Item 5</a>
Ao iniciar a aplicação, podemos acessar o componente ItemComponent
e passar o id=5
através do link.
Problemas com Múltiplos Parâmetros de Rotas
Este método funciona bem para uma única rota, mas se tivermos vários links apontando para o mesmo componente com diferentes ids, como:
<a routerLink="/item/5">Item 5</a>
<a routerLink="/item/8">Item 8</a>
Se navegarmos primeiro para o link do Item 5
, o componente ItemComponent receberá id=5
. Contudo, ao clicar no segundo link, o componente continuará exibindo o valor id=5
.
Para resolver esse problema, precisamos atualizar dinamicamente o valor de id
dentro do componente. Vamos alterar o código do ItemComponent
:
import { Component } from "@angular/core";
import { ActivatedRoute } from "@angular/router";
import { Subscription } from "rxjs";
@Component({
selector: "item-info",
template: `<h2>Modelo {{ id }}</h2>`,
})
export class ItemComponent {
id: number | undefined;
private subscription: Subscription;
constructor(private activateRoute: ActivatedRoute) {
this.subscription = activateRoute.params.subscribe((params) => (this.id = params["id"]));
}
}
O método subscribe()
permite que o componente reaja às mudanças nos parâmetros de rota, garantindo que ele receba o novo valor ao navegar para diferentes URLs.
Outra abordagem para resolver essa questão é utilizar o método ngOnInit
no ItemComponent:
import { Component, OnInit } from "@angular/core";
import { ActivatedRoute } from "@angular/router";
import { switchMap } from "rxjs/operators";
@Component({
selector: "item-info",
template: `<h2>Modelo {{ id }}</h2>`,
})
export class ItemComponent implements OnInit {
id: number | undefined;
constructor(private route: ActivatedRoute) {}
ngOnInit() {
this.route.paramMap.pipe(switchMap((params) => params.getAll("id"))).subscribe((data) => (this.id = +data));
}
}
Neste caso, o valor de id
é obtido no método ngOnInit
, onde acessamos a propriedade paramMap
da rota, que representa um Observable<ParamMap>
(um mapa de parâmetros de rota e query string). Utilizamos o método pipe()
para aplicar operadores RxJS, como o switchMap()
, que nos permite extrair o valor do parâmetro id
e atualizá-lo dinamicamente.
Dessa forma, o componente consegue gerenciar corretamente diferentes parâmetros de rota ao longo da navegação.