Home > Enterprise >  Nuxt.js cannot update head() properties from asyncData()
Nuxt.js cannot update head() properties from asyncData()

Time:03-24

I created a server-side rendered Vue.js blog using Nuxt.js with Typescript and Ghost but I'm having some issues to update html metatag using data from asyncData().

From Nuxt.js documentation I know that asyncData() is called every time before loading page components and merges with component data.

I'm getting this error:

Property 'title' does not exist on type '{ asyncData({ app, params }: Context): Promise<{ title: string | undefined; excerpt: string | undefined; feature_image: Nullable | undefined; html: Nullable | undefined; }>; head(): any; }'.

This is my code:

<script lang="ts">
import { Context } from '@nuxt/types'
import { PostOrPage } from 'tryghost__content-api'

export default {
  async asyncData ({ app, params }: Context) {
    const post: PostOrPage = await app.$ghost.posts.read(
      {
        slug: params.slug
      },
      { include: 'tags' }
    )

    return {
      title: post.title,
      excerpt: post.excerpt,
      feature_image: post.feature_image,
      html: post.html
    }
  },

  head () {
    return {
      title: this.title,
      meta: [
        {
          hid: 'description',
          name: 'description',
          content: this.excerpt
        }
      ]
    }
  }
}
</script>

I already tried some solutions like using data() to set a default value for each item but nothing. Do you have any suggestion?

CodePudding user response:

Without a typescript plugin like nuxt-property-decorator you won't have Typescript support for nuxt (type checking and autocomplete still won't work).

That's why asyncData & fetch should be in Component options.

@Component({
  asyncData (ctx) {
    ...
  }
})
export default class YourClass extends Vue {
...
}

instead of

@Component
export default class YourClass extends Vue {
  asyncData (ctx) {
    ...
  }
}

If you still want to use asyncData() inside of your component class instead of setting the option, see this working example

CodePudding user response:

Here is the working code after implementing the suggestion from @nonNumericalFloat :

import { Component, Vue } from 'nuxt-property-decorator'
import { Context } from '@nuxt/types'
import { PostOrPage } from 'tryghost__content-api'

import Title from '~/components/Title.vue'

@Component({
  components: {
    Title
  }
})
export default class Page extends Vue {
  post!: PostOrPage

  async asyncData ({ app, params }: Context) {
    const post: PostOrPage = await app.$ghost.posts.read(
      {
        slug: params.slug
      },
      { include: 'tags' }
    )

    return {
      post
    }
  }

  head () {
    return {
      title: this.post.title,
      meta: [
        {
          hid: 'description',
          name: 'description',
          content: this.post.excerpt
        }
      ]
    }
  }
}
  • Related