Mudar o título da página de acordo com a rota - Angular
O título (<title>
) da sua página é utilizado em vários lugares, porém todos tme um único propósito: dar uma boa ideia sobre o conteúdo abordado.
Para te dar uma ideia, pessoas com deficiência visual utilizam programas que fazem a leitura da tela. Ao focar em uma aba de um navegador, normalmente o título da página é lido e assim a pessoa pode decidir se aquele conteúdo é relevante ou não para sua pesquisa.
Uma técnica comum de navegação para usuários de tecnologias assistivas é ler o título da página a fim de deduzir o que ela contém. Isso ocorre porque navegar pela página para determinar o conteúdo dela pode ser confuso e consumir muito tempo.
fonte: https://developer.mozilla.org/pt-BR/docs/Web/HTML/Element/title#specifications
Além disso, podemos comentar sobre a importância do seu título para os mecanismos de busca.
A figura abaixo mostra o navegador renderizando o conteúdo do <title>
na aba:
Agora vamos focar no mundo Angular! Se você está começando com Angular provavelmente já percebeu que existe um arquivo chamado index.html
e que o <title>
da sua aplicação está lá:
Quando começamos um projeto novo não existe um arquivo ou configuração pronta para alterar o título de acordo com a rota. Por exemplo, considere uma aplicação com as seguintes rotas:
/home
/sobre
/contato
Conforme o usuário navega entre as rotas o título permanece o mesmo, veja abaixo ao lado direito (<title>Olá</title>
):
Gerenciando o título com a classe Title
O Angular fornece uma classe chamada Title
. Esta classe nos permite alterar o título da aplicação. Abaixo há um exemplo bem direto sobre isto:
Sabendo que o Title
nos permite trocar o título, podemos alterar o título dentro de cada componente vinculado a uma rota:
/* ************************************** */
/* home.component.ts */
/* rota: /home */
/* ************************************** */
/* ... */
export class HomeComponent {
constructor(private titleService: Title) {
this.titleService.setTitle('Home');
}
}
/* ************************************** */
/* sobre.component.ts */
/* rota: /sobre */
/* ************************************** */
/* ... */
export class SobreComponent {
constructor(private titleService: Title) {
this.titleService.setTitle('Sobre');
}
}
/* ************************************** */
/* Contato.component.ts */
/* rota: /contato */
/* ************************************** */
/* ... */
export class ContetoComponent {
constructor(private titleService: Title) {
this.titleService.setTitle('Contato');
}
}
Apesar de atingirmos o objetivo deste texto, alterar o título de acordo com a rota, podemos observar que esta estratégia irá funcionar bem para pequenas aplicações, mas conforme as rotas forem crescendo ficaria inviável essa excessiva duplicação de código.
Vamos avançar um pouco mais com o objetivo de criar a lógica acima em um único lugar - veja a seguir.
Router - identificando a rota ativa
Vamos fazer um rápido "parênteses" antes de voltarmos a falar sobre as rotas e seus títulos.
Inicialmente nossa aplicação carrega o AppComponent
. Ele é o componente root que o Angular cria e insere no index.html
.
Quando trabalhamos com rotas, dentro de seu template (app.component.html
) encontraremos o elemento <router-outlet>
que é onde os componentes são carregados de acordo com a rota ativa. A figura abaixo ilustra este cenário:
Aqui é importante perceber que o AppComponent
continua ativo independente da rota.
Quem vêm do ASP.NET pode fazer uma pequena analogia à MasterPage, mas lembre-se de que o mecanismo é totalmente diferente.
Então coisas que são comuns a toda a aplicação normalmente serão encontradas no template do AppComponent
, como menu, footer, headers, etc. Lembre-se de que isto não é uma regra, como eu disse: normalmente.
Se o AppComponent
é o root de nossa aplicação, significa que ele sempre está ativo independente da rota que estamos. Então independente da rota, no nosso cenário, o AppComponent
está sempre lá. Sendo assim, podemos utilizar a classe Router
para monitorar qual a rota que está ativa e assim determinar o valor do título:
Perceba que nosso código funciona bem. Conseguimos adicionar um código para gerenciar os títulos dentro de um único lugar (AppComponent
), porém novamente temos o problema do crescimento das rotas. Conforme a aplicação for crescendo teremos que adicionar vários case:
neste switch
.
Pensando em melhorar um pouco mais, vamos focar no arquivo app-routing.module
.
Route.data - adicionando informações às rotas
No arquivo app-routing.module.ts
onde normalmente declaramos as rotas, é possível notar que as rotas são do tipo Routes
(const routes: Routes = [ /* ... */ ]
). Se olharmos melhor a definição do Routes
temos o seguinte:
export declare type Routes = Route[];
Então cada rota que declaramos é do tipo Route
e o conjunto de rotas define o Route[]
que é a mesma coisa que Routes
. Se novamente observarmos melhor, Route
é uma interface com vários campos:
export declare interface Route {
path?: string;
pathMatch?: string;
matcher?: UrlMatcher;
component?: Type<any>;
redirectTo?: string;
outlet?: string;
canActivate?: any[];
canActivateChild?: any[];
canDeactivate?: any[];
canLoad?: any[];
/**
* Additional developer-defined data provided to the component via
* `ActivatedRoute`. By default, no additional data is passed.
*/
data?: Data;
resolve?: ResolveData;
children?: Routes;
loadChildren?: LoadChildren;
runGuardsAndResolvers?: RunGuardsAndResolvers;
}
Veja que há um campo opcional chamado data
com a tipagem Data
:
export declare type Data = {
[name: string]: any;
};
Podemos utilizar este campo para atribuir quaisquer valores que julguemos necessário.
Thedata
property in the third route is a place to store arbitrary data associated with this specific route. The data property is accessible within each activated route. Use it to store items such as page titles, breadcrumb text, and other read-only, static data.
fonte: https://angular.io/guide/router-reference
Por exemplo, podemos adicionar um valor de título na configuração de cada rota para posteriormente efetuar sua leitura quando a rota estiver ativa. Veja abaixo:
Para efetuar a leitura do conteúdo que está no data
podemos recorrer ao ActivatedRoute
:
Agora chegamos no cenário desejado, atualizar o título de acordo com a rota ativa mantendo esta gestão em um único lugar (AppComponent
):
TranslateService - tradução dos títulos
Caso esteja utilizando o TranslateService
para trabalhar com vários idiomas, podemos seguir a mesma lógica, porém ao invés de adicionarmos o título no app-routing.module.ts
vamos adicionar apenas a chave de tradução:
Também é necessário modificar o AppComponent
para sabermos se o usuário alterou o idioma. Sempre que alterar o idioma temos que traduzir o título:
Considerações
A partir do Angular 14 a gestão do título ficará um pouco diferente. Vou deixar um link onde li sobre este assunto e em breve abordarei novamente o tema:
Links interessantes: