angular
April 18

Управление заголовками страниц в Angular

Начиная с версии 14, Angular добавили опцию установки заголовка страницы через маршрутизатор. Теперь разработчик может установить свойство title в определении маршрута:

export const routes: Routes = [
  {
    path: 'todos',
    title: 'Todos',
    loadChildren: () => import('./todos-page/todos.routes')
                                      .then(m => m.todosRoutes)
  }
]

В случаях когда требуется динамический заголовок можно передать класс, реализующий интерфейс Resolve:

import { ActivatedRouteSnapshot, Resolve, Routes } from '@angular/router';

@Injectable({ providedIn: 'root' })
class TodoTitle implements Resolve<string> {
  constructor(private todosRepo: TodosRepository) { }

  resolve(route: ActivatedRouteSnapshot) {
    // We can also use `route.params.id`

    return this.todosRepo.active$.pipe(
      map(todo => todo.title),
      take(1)
    );
  }
}

const todosRoutes: Routes = [
  {
    path: '',
    loadComponent: () =>
      import('./todos-page.component').then((m) => m.TodosPageComponent),
    children: [
      {
        path: ':id',
        title: TodoTitle,
        loadComponent: () =>
          import('./todo-page/todo-page.component').then(
            (m) => m.TodoPageComponent
          ),
      },
    ],
  },
];

Еще один вариант использования, если мы хотим, чтобы название компании появлялось перед каждым заголовком в приложении. Такое поведение можно реализовать, используя собственную стратегию заголовка (TitleStrategy):

import { bootstrapApplication, Title } from '@angular/platform-browser';
import { RouterModule, RouterStateSnapshot, TitleStrategy } from '@angular/router';

@Injectable({ providedIn: 'root' })
export class TemplatePageTitleStrategy extends TitleStrategy {
  constructor(private readonly title: Title) {
    super();
  }

  override updateTitle(routerState: RouterStateSnapshot) {
    const title = this.buildTitle(routerState);
    if (title !== undefined) {
      this.title.setTitle(`App Name | ${title}`);
    }
  }
}

bootstrapApplication(AppComponent, {
  providers: [
    { provide: TitleStrategy, useClass: TemplatePageTitleStrategy }
  ]
})