Rotas Filhas em Angular
Nos temas anteriores, trabalhamos com rotas simples, onde o sistema de roteamento seleciona um componente com base na URL e o insere no componente principal, o AppComponent
. Mas o que acontece quando o componente escolhido precisa, por sua vez, incluir outro componente como conteúdo interno, dependendo da solicitação? Nesse caso, usamos as rotas filhas (child routes).
Por exemplo, vamos usar um projeto dos temas anteriores com a seguinte estrutura:
helloapp/ ├── src/ │ ├── app/ │ │ ├── about.component.ts │ │ ├── app.component.ts │ │ ├── app.config.ts │ │ ├── item.component.ts │ │ ├── home.component.ts │ │ ├── not-found.component.ts │ ├── main.ts │ ├── index.html ├── angular.json ├── package-lock.json ├── package.json └── tsconfig.json
Agora, vamos adicionar dois componentes simples na pasta src/app
. Primeiro, adicionamos o arquivo item.details.component.ts
:
import { Component } from "@angular/core";
@Component({
selector: "item-details",
template: `<h2>Informações sobre o produto</h2>`,
})
export class ItemDetailsComponent {}
Em seguida, adicionamos o segundo arquivo item.stat.component.ts
:
import { Component } from "@angular/core";
@Component({
selector: "item-stat",
template: `<h2>Estatísticas do produto</h2>`,
})
export class ItemStatComponent {}
Agora temos dois componentes: ItemDetailsComponent
e ItemStatComponent
, que mostram diferentes aspectos do mesmo produto. Ambos estão logicamente associados ao ItemComponent
, que também está relacionado a um produto específico.
Poderíamos definir rotas diretas para esses componentes da seguinte forma:
{ path: "item/:id/details", component: ItemDetailsComponent },
{ path: "item/:id/stat", component: ItemStatComponent },
Nesse caso, id
é um parâmetro de rota que representa o ID do produto. No entanto, essas rotas ignorariam o ItemComponent
, que é o principal componente responsável por gerenciar o produto. Para solucionar isso, precisamos reorganizar as rotas. Vamos modificar o arquivo app.config.ts
da seguinte maneira:
import { ApplicationConfig } from "@angular/core";
import { provideRouter, Routes } from "@angular/router";
import { HomeComponent } from "./home.component";
import { ItemComponent } from "./item.component";
import { ItemStatComponent } from "./item.stat.component";
import { ItemDetailsComponent } from "./item.details.component";
// Definindo rotas filhas
const itemRoutes: Routes = [
{ path: "details", component: ItemDetailsComponent },
{ path: "stat", component: ItemStatComponent },
];
const appRoutes: Routes = [
{ path: "item/:id", component: ItemComponent, children: itemRoutes },
{ path: "", component: HomeComponent },
];
export const appConfig: ApplicationConfig = {
providers: [provideRouter(appRoutes)],
};
Cada rota filha é mapeada para uma parte específica da URL. Para aplicar essas rotas, usamos a propriedade children na rota do componente ItemComponent
:
{ path: "item/:id", component: ItemComponent, children: itemRoutes }
Agora vamos modificar o ItemComponent
:
import { Component } from "@angular/core";
import { ActivatedRoute, RouterOutlet } from "@angular/router";
@Component({
selector: "item-info",
standalone: true,
imports: [RouterOutlet],
template: `<h1>Produto {{ id }}</h1>
<router-outlet></router-outlet>`,
})
export class ItemComponent {
id: number;
constructor(private route: ActivatedRoute) {
route.params.subscribe((params) => (this.id = params["id"]));
}
}
Aqui, o elemento <router-outlet></router-outlet>
é usado para inserir os componentes ItemDetailsComponent
e ItemStatComponent
.
Também vamos alterar o componente principal, AppComponent
, adicionando links para testar os componentes ItemDetailsComponent
e ItemStatComponent
:
import { Component } from "@angular/core";
import { RouterOutlet, RouterLink } from "@angular/router";
@Component({
selector: "my-app",
standalone: true,
imports: [RouterOutlet, RouterLink],
styles: `a { padding: 3px; }`,
template: `<div>
<nav>
<a routerLink="">Início</a> | <a routerLink="/item/5/details">Informações sobre o produto</a> |
<a routerLink="/item/5/stat">Estatísticas do produto</a>
</nav>
<router-outlet></router-outlet>
</div>`,
})
export class AppComponent {}
Ao clicar nesses links, o roteamento será ativado para o componente ItemComponent
, que receberá o parâmetro de rota id
. Além disso, o roteamento será feito para o ItemDetailsComponent
ou ItemStatComponent
, dependendo se o caminho termina com "details" ou "stat".