change - Añadir dinámicamente meta descripción basada en ruta en Angular
meta tags angular 4 (5)
Estoy usando Angular 5 para construir un pequeño sitio web tipo folleto. Hasta ahora, tengo mis rutas configuradas y el título de la página cambia dinámicamente según la ruta activada. Conseguí este trabajo usando las instrucciones en este blog: https://toddmotto.com/dynamic-page-titles-angular-2-router-events
Actualmente estoy almacenando mis rutas y títulos en app.module.ts como tal:
imports: [
BrowserModule,
RouterModule.forRoot([
{
path: '''',
component: HomeComponent,
data: {
title: ''Home''
}
},
{
path: ''about'',
component: AboutComponent,
data: {
title: ''About''
}
},
{
path: ''products-and-services'',
component: ProductsServicesComponent,
data: {
title: ''Products & Services''
}
},
{
path: ''world-class-laundry'',
component: LaundryComponent,
data: {
title: ''World Class Laundry''
}
},
{
path: ''contact'',
component: ContactComponent,
data: {
title: ''Contact''
}
},
{
path: ''**'',
component: NotFoundComponent,
data: {
title: ''Page Not Found''
}
}
])
],
También me gustaría almacenar mis meta descripciones allí, si las agrego bajo data:
sería bastante fácil.
Estoy ingresando los datos de ese título con el siguiente código, que se indica en el enlace del blog anterior:
ngOnInit() {
this.router.events
.filter((event) => event instanceof NavigationEnd)
.map(() => this.activatedRoute)
.map((route) => {
while (route.firstChild) route = route.firstChild;
return route;
})
.filter((route) => route.outlet === ''primary'')
.mergeMap((route) => route.data)
.subscribe((event) => {
this.titleService.setTitle(event[''title'']);
});
}
Entonces, mi pregunta es, ¿hay una manera de establecer dinámicamente la meta descripción usando el mismo método? Si hay una manera de combinar el título de la página y la función de descripción meta, sería ideal.
Tengo un entrenamiento angular muy limitado, por lo que esta podría ser una pregunta nooby. Soy más de un tipo de diseñador / css / html.
Primero crea un SEOService o algo como a continuación:
import {Injectable} from ''@angular/core'';
import { Meta, Title } from ''@angular/platform-browser'';
@Injectable()
export class SEOService {
constructor(private title: Title, private meta: Meta) { }
updateTitle(title: string) {
this.title.setTitle(title);
}
updateDescription(desc: string) {
this.meta.updateTag({ name: ''description'', content: desc })
}
Después de inyectar el servicio SEOS en su componente, configure las metaetiquetas y el título en el método OnInit
ngOnInit() {
this.router.events
.filter((event) => event instanceof NavigationEnd)
.map(() => this.activatedRoute)
.map((route) => {
while (route.firstChild) route = route.firstChild;
return route;
})
.filter((route) => route.outlet === ''primary'')
.mergeMap((route) => route.data)
.subscribe((event) => {
this._seoService.updateTitle(event[''title'']);
//Updating Description tag dynamically with title
this._seoService.updateDescription(event[''title''] + event[''description''])
});
}
Edición: Para RxJs 6+ que usa un operador de tubería
ngOnInit() {
this.router.events.pipe(
filter((event) => event instanceof NavigationEnd),
map(() => this.activatedRoute),
map((route) => {
while (route.firstChild) route = route.firstChild;
return route;
}),
filter((route) => route.outlet === ''primary''),
mergeMap((route) => route.data)
)
.subscribe((event) => {
this._seoService.updateTitle(event[''title'']);
//Updating Description tag dynamically with title
this._seoService.updateDescription(event[''title''] + event[''description''])
});
}
Luego configura tus rutas como
{
path: ''about'',
component: AboutComponent,
data: {
title: ''About'',
description:''Description Meta Tag Content''
}
},
En mi humilde opinión, esta es una forma clara de tratar con las etiquetas meta. Puedes actualizar las etiquetas específicas de facebook y twitter más fácilmente.
Puede hacer lo siguiente desde Angular (en realidad, la solución solo necesita jQuery, no algo particular de Angular)
En la configuración del router:
{
path: ''about'',
component: AboutComponent,
data: {
title: ''About'',
description: ''Here some description''
}
},
En su componente:
...
.subscribe((event) => {
this.titleService.setTitle(event[''title'']);
$(''meta[name=description]'').attr(''content'', event[''description'']);
});
Si no desea utilizar jQuery, existen funciones simples de JavaScript para encontrar los elementos meta y cambiar sus atributos ( getElementsByTagName y getAttribute ). El código completo para la alternativa de JavaScript se puede encontrar en esta otra pregunta SO aquí .
Nota: También consideraría almacenar el título y la descripción como campos privados en los propios componentes, en lugar de en la configuración del enrutador. Esto evita la necesidad de suscribirse a cualquier cosa, y deja solo las cosas relacionadas con el enrutador en la configuración del enrutador.
Title
y angular.io/api/platform-browser/Meta son proveedores que se introdujeron en Angular 4 y se supone que deben hacer esto tanto en el servidor como en el lado del cliente.
Para crear o actualizar la etiqueta del title
y la etiqueta meta de la description
, es:
import { Meta, Title } from ''@angular/platform-browser'';
...
constructor(public meta: Meta, public title: Title, ...) { ... }
...
this.meta.updateTag({ name: ''description'', content: description });
this.title.setTitle(title);
Aquí están las partes relevantes de mi proyecto. (Angular 2/4)
app-routing.module.ts:Rutas:
... const appRoutes: Routes = [
{
path: ''path1'', loadChildren: ''./path1#path1Module'',
data: {
title: ''...'',
description: ''...'',
keywords: ''...''
}
},
{
path: ''path2'', loadChildren: ''./path2#path2Module'',
data: {
title: ''...'',
description: ''...'',
keywords: ''...''
}
} ...
app.component.ts (o su componente bootstrap):
importaciones:
// imports
import { Component, OnInit} from ''@angular/core'';
import { Router, ActivatedRoute, NavigationEnd } from ''@angular/router'';
import ''rxjs/add/operator/filter'';
import ''rxjs/add/operator/map'';
import ''rxjs/add/operator/mergeMap'';
import { Title,Meta } from ''@angular/platform-browser'';
constructor:
// constructor:
constructor(private router: Router,
private route: ActivatedRoute,
private titleService: Title, private meta: Meta) {}
Método ngOnInit ():
ngOnInit() {
this.router.events
.filter((event) => event instanceof NavigationEnd)
.map(() => this.route)
.map((route) => {
while (route.firstChild) route = route.firstChild;
return route;
})
.filter((route) => route.outlet === ''primary'')
.mergeMap((route) => route.data)
.subscribe((event) => {
this.updateDescription(event[''description''], event[''keywords''], event[''title'']);
});
}
método que actualiza las etiquetas de título y meta -> llamadas desde ngOnInit ():
updateDescription(desc: string, keywords: string, title: string) {
this.titleService.setTitle(title);
this.meta.updateTag({ name: ''description'', content: desc })
this.meta.updateTag({ name: ''keywords'', content: keywords })
this.meta.updateTag({ name: ''og:title'', content: title })
this.meta.updateTag({ name: ''og:description'', content: desc })
}
Espero eso ayude.
Solución Angular 6+ y RxJS 6+ para establecer títulos de forma dinámica en el cambio de ruta
Si / cuando actualizas a Angular 6 esta es la solución.
Este servicio:
- Actualizar el título del meta en el cambio de ruta.
- Opción de anular el título por cualquier motivo que desee.
Crea / cambia tu servicio SEO / meta a lo siguiente.
import { Injectable } from ''@angular/core'';
import { Title, Meta } from ''@angular/platform-browser'';
import { Router, NavigationEnd, ActivatedRoute } from ''@angular/router'';
import { filter, map, mergeMap } from ''rxjs/operators'';
@Injectable({
providedIn: ''root''
})
export class MetaService {
constructor(
private titleService: Title,
private meta: Meta,
private router: Router,
private activatedRoute: ActivatedRoute
) { }
updateMetaInfo(content, author, category) {
this.meta.updateTag({ name: ''description'', content: content });
this.meta.updateTag({ name: ''author'', content: author });
this.meta.updateTag({ name: ''keywords'', content: category });
}
updateTitle(title?: string) {
if (!title) {
this.router.events
.pipe(
filter((event) => event instanceof NavigationEnd),
map(() => this.activatedRoute),
map((route) => {
while (route.firstChild) { route = route.firstChild; }
return route;
}),
filter((route) => route.outlet === ''primary''),
mergeMap((route) => route.data)).subscribe((event) => {
this.titleService.setTitle(event[''title''] + '' | Site name'');
});
} else {
this.titleService.setTitle(title + '' | Site name'');
}
}
}
Importa tu servicio y llámalo en el contructor.
app.component.ts
constructor(private meta: MetaService) {
this.meta.updateTitle();
}
Y esto todavía requiere formatear rutas como esta.
Archivo de ruta.ts
{
path: ''about'',
component: AboutComponent,
data: {
title: ''About'',
description:''Description Meta Tag Content''
}
},
Espero que esto ayude a usted y otras personas que buscan actualizar el título / meta dinámicamente en Angular 6.