Search code examples
vue.jsmeta-tagsvue-meta

Vue Meta - Title not displayed properly when filled with dynamic data value


I have a pretty basic setup in my Vue app for my blog, where I have /blog, which is a listing of my blog posts, and then /blog/:slug, where slug is the slog for the individual post (e.g. mysite.com/blog/my-awesome-blog-post. I'm using vue-meta for the meta tags, and everything works great - for everything except the tag for the individual blog posts. My setup is:

App.vue

export default {
  metaInfo: {
    title: 'Building great web experiences',
    titleTemplate: 'My Website | %s',
  },
  meta: [
    { charset: 'utf-8' },
    { name: 'description', content: 'The website for my organization' },
    { name: 'viewport', content: 'width=device-width, initial-scale=1' }
  ]
}

Blog.vue

export default {
  metaInfo: {
    title: 'Blog Home'
  },

BlogPost.vue (following the vue-meta docs)

export default {
data() {
  metaDescription: '',
},
  metaInfo() {
    return {
      title: this.post.data.title,
      meta: [
        { vmid: 'description', name: 'description', content: this.metaDescription}
      ]
    }
  },

...
methods: {
    getPost() {
      const vm = this;
      butter.post
        .retrieve(this.$route.params.slug)
        .then(res => {
          vm.post = res.data;
          vm.metaDescription = vm.post.data.summary;
        })
        .catch(res => {
          console.log(res);
        });
    }
  },

The problem is that when I go to a blog post page, the title metatag is still My Site | Blog Home, instead of My Site | My Awesome Blog Post. If I put a static string in for title, it works fine. And, if I inspect the object returned by the metaInfo() function in the Vue devtools, it shows title with the appropriate value. Am I doing something wrong, or is this a bug? According to the docs this is "easy", but it doesn't seem that way.


Solution

  • As noted in my comment in the GitHub issue I filed, I made a small change that worked (actually, there were a couple that worked). The first was to create a data variable called metaTitle, fill it in getPost(), and use that in metaInfo():

    data() {
        return {
          post: {},
          metaTitle: '',
          metaDescription: ''
        };
      },
      metaInfo() {
        return {
          title: this.metaTitle,
          meta: [
            { vmid: 'description', name: 'description', content: this.metaDescription}
          ]
        }
      },
     methods: {
        getPost() {
          const vm = this;
          butter.post
            .retrieve(this.$route.params.slug)
            .then(res => {
              vm.post = res.data.data;
              vm.metaTitle = vm.post.data.title;
              vm.metaDescription = vm.post.summary;
            })
            .catch(res => {
              console.log(res);
            });
        }
      },
    

    I then also tried another twist and made my post object one level smaller:

    .then(res => {
      vm.post = res.data.data;
      vm.metaTitle = vm.post.data.title;
      vm.metaDescription = vm.post.summary;
    })
    

    and used it in metaInfo():

    metaInfo() {
      return {
        title: this.post.title,
        meta: [
          { vmid: 'description', name: 'description', content: this.metaDescription}
        ]
      }
    },
    

    Maybe the issue is that the title data can't be too many levels down in an object? Not sure, but either way works.