Update meta tags in angular universal with external API call

后端 未结 4 1975
庸人自扰
庸人自扰 2020-12-30 12:02

I\'ve spent more than 2 months but could not found a clear solution of how to proceed with angular universal. I\'ve already spent about 6 months in implementing angular univ

相关标签:
4条回答
  • 2020-12-30 12:17

    Stumbled upon this looking for same solution. Using a setTimeout worked for me. Make sure to refresh cache or use incognito mode or you'll miss seeing the metadata (I made this mistake). My research suggests that subscribe for API data must be waited upon before SSR renders page so observable must stay open (but I'm not an expert). https://angular.io/guide/observables. Also, the only way to make it work is to put the response from subscription right into metaService. I'll show what I mean in my code.

    setTimeout( () =>
                  this.seo.setFromJson({
                  title: this.content.title,
                  image: this.content.main_image,
                  description: this.content.blog,
                  author: this.content.name,
                  keyword: ''
                });
        ,0);
    

    My code with solution:

    this.publicFeedService.getPublicProfile(data).subscribe((response:any) => {
            this.memberProfile = response[this.userId];
            setTimeout( () => 
            //Define the meta title using profile data
            this.titleService.setTitle('The best investment ideas from ' + response[this.userId].firstName + ' ' + response[this.userId].lastName), 0);
            setTimeout( () =>         
            //Define the meta tags using the user profile data
            this.metaService.addTags([
              {name: 'keywords', content: 'investing ideas, stock ideas, financial profile'},
              {name: 'description', content: response[this.userId].about},
              {name: 'robots', content: 'index, follow'}
            ]), 0);
    
    0 讨论(0)
  • 2020-12-30 12:28

    Couldn't find an easy way to do it but here's a temporary/hacky solution provided by a GitHub user here and I'm quoting his answer directly:

    //all imports
    enableProdMode();
    
    export const app = express();
    
    const mysql = require('mysql');
    const httpRequest = require("request");
    // all other consts
    
    app.engine('html', ngExpressEngine({
      bootstrap: AppServerModuleNgFactory,
      providers: [
        provideModuleMap(LAZY_MODULE_MAP)
      ]
    }));
    //all other piece of code in server.ts
    
    app.get('/*', (req, res) => {
      res.render('index', {req, res}, (err, html) => {
        if (html) {
            
            //console.log(html);
            // This is where you get hold of HTML which "is about to be rendered"
        
            // after some conditional checks make a HTTP call
            let url = 'http://....';
            httpRequest.get(url, (error, response, body) => {
                            if(error) {
                                return console.log(error);
                            }
                            const respBody = JSON.parse(body);
                            if(respBody){
                                  html = html.replace(/\$TITLE/g, respBody.title);
                                  html = html.replace(/\$DESCRIPTION/g, respBody.description);
                                  html = html.replace(/\$OG_META_KEYWORDS/g, respBody.metaKeywords);
                                  html = html.replace(/\$OG_META_DESCRIPTION/g, respBody.metaDescription);
                                  html = html.replace(/\$OG_DESCRIPTION/g, respBody.ogDescription);
                                  html = html.replace(/\$OG_TITLE/g, respBody.ogTitle);
                                  html = html.replace(/\$OG_IMAGE/g, respBody.img);
                                  html = html.replace(/\$OG_SITE/g, respBody.ogSite);
                            }
                            res.send(html);
                });
         }
      }
    }
    

    And in index.html, create template values as below:

        <title>$TITLE</title>
    
        <meta name="description" content="$DESCRIPTION"/> 
        <meta name="keywords" content="$OG_META_KEYWORDS" />
        <meta name="metaDescription" content="$OG_META_DESCRIPTION"/> 
        <meta name="metaKeywords" content="$OG_META_KEYWORDS" />
        <meta property="og:title" content="$OG_TITLE" />
        <meta property="og:description" content="$OG_DESCRIPTION" />
        <meta property="og:site_name" content="$OG_SITE" /> 
        <meta property="og:type" content="website" />   
        <meta property="og:image" content="$OG_IMAGE" />
    
    0 讨论(0)
  • 2020-12-30 12:30

    First Add all required meta tags in index.html file like this

    Then update the meta tags in each required component, use meta.updateTag() as below

    This one worked for me.

    I try to create service to update but that not worked, its working only when meta update added in the same component.

    0 讨论(0)
  • 2020-12-30 12:31

    I implemented setting title on Angular 2 Universal. It should be done using Renderer, like this:

    1.Import Renderer inside of component:

    import {Renderer } from '@angular/core';
    

    2.Add dependency inside of constructor:

    constructor
        (
            ...
            private renderer: Renderer
        ) {}
    

    3.Use it now for setting title:

    renderer.setText(renderer.selectRootElement('title'), value);
    
    0 讨论(0)
提交回复
热议问题