DEV Community

Cover image for Updating Vue Composition-Api Metas
Mikaleb
Mikaleb

Posted on

Updating Vue Composition-Api Metas

After a little head scratch, I found a way to easily update your data if you have a metadata you want to update in a Composition-Api powered Nuxt application, even when they are Async :

<template>
  <div>Your content</div>
</template>

<script lang="ts">
import { defineComponent, ref, onMounted } from '@vue/composition-api'
import usePosts from '~/composables/use-posts'

export default defineComponent({
  name: 'PageArticle',
  head() {
    return {
      title: `${this.title}`,
      meta: [
        { name: 'og:title', content: `${this.title}`, hid: 'og:title' },
      ]
    }
  },

  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  setup(props, ctx) {
    const { fetchArticleForUserLang, article } = usePosts({ ctx })
    const slug = ctx.root.$route.params?.article
    let title = ref('Cuisine De Geek')

    onMounted(async () => {
      await fetchArticleForUserLang({ articleSlug: slug, subcategory: 'article' })
      if (article.value) {
        title.value = article.value[0].title
      }
    })

    return { article, title }
  }
})
</script>

Enter fullscreen mode Exit fullscreen mode

Okay so break-it-down-time :

<template>
  <div>Your content</div>
</template>
Enter fullscreen mode Exit fullscreen mode

Nothing fancy here, just the init of your template content, if you want to display the data (could be a good idea at one point).



<script lang="ts">
import { defineComponent, ref, onMounted } from '@vue/composition-api'
import usePosts from '~/composables/use-posts'
Enter fullscreen mode Exit fullscreen mode

Here, we import the method needed from the composition-api for everything to work correctly : defineComponent, ref to create a dynamic data later, and onMounted to do something as soon as this component/page is called.

The usePosts file called is a separate file I made to handle the logic of loading the data from a separate api (for the record here it's a wordpress REST api).

export default defineComponent({
  name: 'PageArticle',
  head() {
    return {
      title: `${this.title}`,
      meta: [
        { name: 'og:title', content: `${this.title}`, hid: 'og:title' },
      ]
    }
  },
Enter fullscreen mode Exit fullscreen mode

Ah, the big part ! Here, we define the name of our component, then we tell it to change the <head> section of our page.

Because Nuxt use Vue-Meta by default, we can use the head() method in our defineComponent.

Great so now we tell it to use this.title to replace title of the page and og:title. But where do we load this data in particular ?

Well in our setup !

// eslint-disable-next-line @typescript-eslint/no-unused-vars
  setup(props, ctx) {
    const { fetchArticleForUserLang, article } = usePosts({ ctx })
    const slug = ctx.root.$route.params?.article
    let title = ref('Cuisine De Geek') 
Enter fullscreen mode Exit fullscreen mode

Here, first I tell eslint to stop bothering me with the fact that I don't use props in this case.
Then i want to get my method fetchArticleForUserLang and the data article that the method will load later.

I store the slug from the route to call the correct article from this slug later and then I set a variable title that is a ref to be able to update it later on a different life cycle of the application :

 onMounted(async () => {
      await fetchArticleForUserLang({ articleSlug: slug, subcategory: 'article' })
      if (article.value) {
        title.value = article.value[0].title
      }
    })

    return { article, title }
Enter fullscreen mode Exit fullscreen mode

When the component or page (here a page), we tell it to be async to be able to await for our method fetchArticleForUserLang to actually find the data and set it to the article variable (all made behind the scene in the usePosts file).

We check that the article have an actual data (.value since it's a ref) then we tell it to assert the value of the title to our brand new article title.

We finish of by returning our article value and our title ET VOILA.

Top comments (0)