Angular — это MVC-фреймворк для создания одностраничных приложений в Javascript.
В этой статье мы узнаем, как установить заголовок браузера (страницы/документа) для всего приложения и как изменить заголовок браузера при перемещении по приложению.
Пример проекта
Пример проекта для демонстрации этой функции. Вы можете скопировать этот проект и запустить его на своем компьютере.
git clone https://github.com/bbachi/angular_title_example.git // install dependencies and run the project npm install npm start
Как установить заголовок браузера для приложения
В каждом одностраничном приложении есть только один файл index.html, который загружается в браузер до появления в нем элементов фреймворка. В Angular нужно загрузить файл index.html, который содержит компонент root, минимизированные js-файлы и файлы CSS.
Это первый файл, который загружается в браузер для приложения Angular. Устанавливаем заголовок для всего приложения в теге title.
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Title for the whole app</title> <base href="/"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" type="image/x-icon" href="favicon.ico"> </head> <body> <app-root></app-root> </body> </html>
Это снимок браузера. Заголовок не меняется при изменении страницы или перемещении по приложению.
Заголовок браузера
Что такое TitleService
Привязка данных или интерполяция в Angular не работает, поскольку тег title находится вне тела, а Angular не имеет к нему доступа. Доступ к объекту Document можно получить напрямую и установить title вручную. Однако Angular не рекомендует использовать этот способ.
Angular предоставляет TitleService для управления заголовком документа. Это простой API для получения и установки заголовка. Сервис предоставляет два метода.
class Title { // получить заголовок getTitle(): string // установить заголовок setTitle(newTitle: string) }
TitleService в действии
Рассмотрим использование TitleService для чтения и установки заголовка текущего документа.
Сервис Title нужно импортировать из angular/platform-browser и добавить в массив Providers. После добавления сервис доступен для использования в любом из компонентов.
import { BrowserModule, Title } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, AppRoutingModule ], providers: [ Title ], bootstrap: [AppComponent] }) export class AppModule { }
Теперь импортируем TitleService в компонент app и добавляем сервис в конструктор, чтобы он был доступен для использования в компоненте.
import { Component } from '@angular/core'; import { Title } from '@angular/platform-browser'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'angulartitle'; constructor(private titleService: Title) {} setDocTitle(title: string) { console.log('current title:::::' + this.titleService.getTitle()); this.titleService.setTitle(title); } }
Теперь помещаем несколько ссылок в файл шаблона компонента приложения. Метод setDocTitle используется для чтения и установки заголовка документа.
<h2>Quick Links: </h2> <ul> <li><a (click)="setDocTitle( 'About' )">About</a>.</li> <li><a (click)="setDocTitle( 'Dashboard' )">Dashboard</a>.</li> <li><a (click)="setDocTitle( 'Profile' )">Profile</a>.</li> <li><a (click)="setDocTitle( 'My Account' )">My Account</a>.</li> </ul>
Теперь заголовок изменяется, а в консоли появляются выходные данные при нажатии на ссылки в разделе Quick Links. Вы можете проверить этот результат, используя копию указанного выше проекта.
Как установить заголовок браузера для каждой страницы
Проблема с вышеупомянутым подходом заключается в том, что эти методы нужно поместить в компонент и вызвать для каждой ссылки, находящейся в шаблонах компонентов.
Однако есть более удобный способ сделать это с помощью модуля Angular Routing и Router API. В примере ниже название браузера изменяется по мере загрузки определенных страниц при нажатии на ссылки в заголовке.
Посмотрим, как можно это реализовать. Во-первых, нужно определить модуль маршрутизации для приложения с объектом data. В этом месте нужно разместить заголовок.
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { AboutComponent } from './about/about.component'; import { MyprofileComponent } from './myprofile/myprofile.component'; import { MyaccountComponent } from './myaccount/myaccount.component'; import { DashboardComponent } from './dashboard/dashboard.component'; const routes: Routes = [ { path: 'about', component: AboutComponent, data: {title: 'About'}}, { path: 'profile', component: MyprofileComponent, data: {title: 'Profile'} }, { path: 'myaccount', component: MyaccountComponent, data: {title: 'My Account'} }, { path: 'dashboard', component: DashboardComponent, data: {title: 'Dashboard'} } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
Теперь в компоненте App нужно импортировать Router и ActivatedRoute, чтобы подписаться на события маршрутизатора и изменить заголовок с помощью Title service.
Подписываемся на события маршрутизатора, получаем доступ к данным с помощью ActivatedRoute и устанавливаем заголовок с помощью TitleService.
import { Component, OnInit } from '@angular/core'; import { Title } from '@angular/platform-browser'; import { Router, NavigationEnd, ActivatedRoute } from '@angular/router'; import { filter, map } from 'rxjs/operators'; // Опущено для краткости export class AppComponent implements OnInit { title = 'angulartitle'; // Опущено для краткости ngOnInit() { const appTitle = this.titleService.getTitle(); this.router .events.pipe( filter(event => event instanceof NavigationEnd), map(() => { const child = this.activatedRoute.firstChild; if (child.snapshot.data['title']) { return child.snapshot.data['title']; } return appTitle; }) ).subscribe((ttl: string) => { this.titleService.setTitle(ttl); }); } }
В файле выше мы также читаем текущий заголовок, если заголовок не определен в маршрутах. Это можно проверить, удалив объект data в одном из маршрутов в примере проекта.
С модулями
Большую часть времени выполняется отложенная загрузка модулей в целях повышения производительности. Нужно внести небольшие изменения из-за наличия вложенных дочерних элементов.
Я создал модуль Users для отложенной загрузки. Загружаем этот модуль для пути users и ProfileComponent для пути profile. Получаем следующий маршрут: /users/profile.
const routes: Routes = [ { path: 'about', component: AboutComponent }, { path: 'profile', component: MyprofileComponent, data: {title: 'Profile'} }, { path: 'myaccount', component: MyaccountComponent, data: {title: 'My Account'} }, { path: 'dashboard', component: DashboardComponent, data: {title: 'Dashboard'} }, { path: 'users', loadChildren: './users/users.module#UsersModule' } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { ProfileComponent } from '../profile/profile.component'; import { ListusersComponent } from '../listusers/listusers.component'; const routes: Routes = [ { path: 'profile', component: ProfileComponent, data: {title: 'User Profile'} }, { path: 'myaccount', component: ListusersComponent, data: {title: 'List Users'} } ]; @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule] }) export class UsersRoutingModule { }
Цикл while должен выполняться до тех пор, пока не будет найден последний дочерний элемент.
ngOnInit() { const appTitle = this.titleService.getTitle(); this.router .events.pipe( filter(event => event instanceof NavigationEnd), map(() => { let child = this.activatedRoute.firstChild; while (child.firstChild) { child = child.firstChild; } if (child.snapshot.data['title']) { return child.snapshot.data['title']; } return appTitle; }) ).subscribe((ttl: string) => { this.titleService.setTitle(ttl); }); }
Вывод в браузере:
Выводы:
- В каждом одностраничном приложении есть index.html.
- Заголовок для всего приложения можно установить с тегом title в разделе head файла index.html.
- Тег title не доступен через привязку данных Angular.
- Angular предоставляет TitleService для получения и установки текущего заголовка документа.
- Получить и установить заголовок для каждой страницы можно в одном месте, подписавшись на маршруты Angular.
- Для вложенных модулей необходимо выполнять цикл до нахождения последнего дочернего элемента.
Заключение
TitleService — это удобный метод для чтения и установки заголовка документа. Angular не рекомендует обращаться к объекту Document вручную для получения и установки заголовка.
Специально для сайта ITWORLD.UZ. Новость взята с сайта NOP::Nuances of programming