В прошлых темах рассматривалась работа с обычными маршрутами. То есть система маршрутизации выбирает один из компонентов на основе url и помещает его в главный компонент AppComponent. Но что если выбранный компонент сам должен принимать в качестве внутреннего содержимого какой-то другой компонент в зависимости от запроса. В этому случае нам надо использовать дочерние маршруты (child route).
К примеру, возьмем проект из прошлых тем:
Добавим в папку src/app два простеньких компонента. Вначале добавим файл item.details.component.ts:
import { Component} from "@angular/core"; @Component({ selector: "item-details", template: `<h2>Информация о товаре</h2>` }) export class ItemDetailsComponent{}
И также добавим второй файл item.stat.component.ts:
import { Component} from "@angular/core"; @Component({ selector: "item-stat", template: `<h2>Статистика товара</h2>` }) export class ItemStatComponent{}
Итак, есть два компонента ItemDetailsComponent и ItemStatComponent, которые условно раскрывают различные стороны одно и того же товара. Логически они относятся к ItemComponent, который также связан с определенным товаром.
Мы бы могли определить прямые маршруты к этим компонентам типа:
{ path: "item/:id/details", component: ItemDetailsComponent}, { path: "item/:id/stat", component: ItemStatComponent},
Где в данном случае id - также параметр маршрута, представляющий условный id товара.
Но такие маршруты будут миновать компонент ItemComponent и никак его не затрагивают. Поэтому нам надо использовать другую организацию маршрутов. Для этого изменим файл app.config.ts следующим образом:
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"; // определение дочерних маршрутов const itemRoutes: Routes = [ { path: "details", component: ItemDetailsComponent}, { path: "stat", component: ItemStatComponent}, ]; const appRoutes: Routes =[ { path: "item/:id", component: ItemComponent}, { path: "item/:id", component: ItemComponent, children: itemRoutes}, { path: "", component: HomeComponent} ]; export const appConfig: ApplicationConfig = { providers: [provideRouter(appRoutes)] };
Каждый из дочерних маршрутов сопоставляется не совсем адресом url, а только с его частью. Далее чтобы применить такие маршруты, у маршрута для компонента ItemComponent применяется свойство children:
{ path: "item/:id", component: ItemComponent, children: itemRoutes},
Теперь изменим ItemComponent:
import { Component} from "@angular/core"; import { ActivatedRoute, RouterOutlet} from "@angular/router"; @Component({ selector: "item-info", standalone: true, imports: [RouterOutlet], template: `<h1>Товар {{id}}</h1> <router-outlet></router-outlet>` }) export class ItemComponent{ id: number; constructor(private route: ActivatedRoute){ route.params.subscribe(params=>this.id=params["id"]); } }
Для вставки компонентов ItemDetailsComponent и ItemStatComponent здесь определен элемент <router-outlet></router-outlet>
.
И изменим главный компонент AppComponent, добавив в него для тестирования ссылки на ItemDetailsComponent и 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="">Главная</a> | <a routerLink="/item/5/details">Информация о товаре</a> | <a routerLink="/item/5/stat">Статистика товара</a> </nav> <router-outlet></router-outlet> </div>` }) export class AppComponent {}
При переходе по подобным ссылкам будет срабатывать маршрутизация к компоненту ItemComponent и ему будет передаваться параметр маршрута - id. И также будет срабатывать маршрутизация к ItemDetailsComponent или ItemStatComponent, если после id идет какой-нибудь сегмент "details" или "stat":