programmatically updating title or tags works inside ngOnInit, but not within subscribe callback function.
See original GitHub issueI’m submitting a … (check one with “x”)
[x] bug report => check the README and search github for a similar issue or PR before submitting
[ ] support request => check the README and search github for a similar issue or PR before submitting
[ ] feature request
Current behavior
Neither this.meta.setTag('description', 'updated description');
or this.meta.setTitle('updated title');
seem to work inside of a subscribe function of an http request to a REST API.
Expected/desired behavior
It should use the default values of the metaService as defined here: https://github.com/nglibs/meta#appmodulets-2 until the http request finishes and the subscribe function is called, then it should use the updated data as defined by the setter functions. Minimal reproduction of the problem with instructions
Follow the above descriptionWhat is the motivation / use case for changing the behavior?
I have data from the server that needs to be put into the meta and title tags for better seo with Google. Please tell us about your environment:
- Angular version: 2.0.X
angular-cli: 1.0.0-beta.26 node: 6.9.3 os: darwin x64 @angular/common: 2.4.5 @angular/compiler: 2.4.5 @angular/core: 2.4.5 @angular/forms: 2.4.5 @angular/http: 2.4.5 @angular/material: 2.0.0-beta.1 @angular/platform-browser: 2.4.5 @angular/platform-browser-dynamic: 2.4.5 @angular/router: 3.4.5 @angular/compiler-cli: 2.4.5
- Browser: [all | Chrome XX | Firefox XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView ]
- Language: [all | TypeScript X.X | ES6/7 | ES5] TypeScript
- Node (for AoT issues):
node --version
=
Issue Analytics
- State:
- Created 6 years ago
- Comments:8 (3 by maintainers)
Top GitHub Comments
So I was having some issues with this as well but I found a pretty good solution.
First the issue: NavigationEnd is called as soon as ngOnInit() finishes and does not wait for subscriptions to complete (and it shouldn’t). Even deferred function won’t add data from the subscriptions. As a hack you could add a function to manually update them when the subscription is done, however, this would be bad SEO as the values would load and then be updated (It’s possible that the googlebot would only read the first values and move on).
The Best Solution: (No changes to @nglibs/meta needed). You need to load the data before the page is rendered. You can do this using the resolver in your routing module. Read this: https://angular.io/docs/ts/latest/api/router/index/Resolve-interface.html Then on your page you can get the data by:
This ensures that the subscription is completed before the component is loaded and all of the metadata can be set immediately after in ngOnInit().
Note: you do not need to use the defer method for this.
@kblestarge Let me know if any of this is unclear and best of luck. @fulls1z3 Awesome job on this project.
Hi @kblestarge, @Raydaq-git. First of all I’d like to thank to @Raydaq-git for coming up quickly and offering such a working solution as well as both your appreciation.
The use of resolver would definitely work in most cases, no doubts. However, I’d like to offer another alternative too: the callback function - which might be a slightly more elegant way to handle this.
I need to clarify that, it could be the case only if you’re using a certain REST call to fetch the data. I mean, there’s a generic service (could be a SEO service returning page titles) that you invoke by passing the page id/key/etc as argument.
Well, if you look at the
app.module.ts
on @nglibs/example-app, you’ll notice that themetaFactory
contains the(key: string) => translate.get(key)
as a callback. It means, the value that the meta property contains gets resolved using that callback function.And, if you look at the config.json, home.routes.ts, and about.routes.ts you’ll notice keys/values like
"defaultPageTitle": "DEFAULT_TITLE"
,"defaultMetaDescription": "DEFAULT_DESC"
, as well as:In this example app, the callback function is the
translate.get
(thanks to @ocombe, for his awesome project ngx-translate). ngx-translate uses these keys are to retrieve translations of meta information on en.json and on tr.json.In your case, a more or less a similar approach should work:
metaFactory
This way, you won’t need to call meta.setTitle/meta.setTag within the subscriptions. Simply pass the keys to a generic service which handles retrieval of seo data, and you’re done 😉
Meantime, I feel that you’re getting the meta info on the entity level - not using a generic method. The callback approach might not work if you stick using separate methods for every object. But there might be a way to make it generic - it’s up to the architecture of your project.
Anyway, please feel free to ask anything you need, I’ll be glad to provide help as far as in me lies.