[Vuejs]-Access page data on component

0👍

You can use nuxtServerInit action in vuex as one way to populate page data.

If you are using nuxt >= 2.12, you can use the new-and-improved fetch hook inside your layouts to make your apollo queries.

0👍

I DID IT!

So, it took a time to figure out, but I’ve learnt a lot during this process.
I’ll let here some references I’ve used to come with this solution.

Let’s go to the way I did it. I don’t know if it’s the best, but worked like a charm here.

I’ve created a hero.js file on my store folder:

  data: {
    title: "",
    subtitle: "",
    imgUrl: ""
  }
})

export const mutations = {
  setData (state, obj) {
    state.data = {...state.data, ...obj}
  }
}

export const getters = {
  getHero (state) {
    return state.data
  }
}

Then on my default.vue I did:

  <div>
    <!-- call Header component -->
    <Header />

    <!-- call Hero component with his slots-->
    <Hero>
      <template v-slot:title>
        <h1 class="title">{{ hero.title }}</h1>
      </template>

      <template v-slot:subtitle>
        <h2 class="subtitle">{{ hero.subtitle }}</h2>
      </template>

      <template v-slot:heroImg>
        <img :src="hero.imgUrl" />
      </template>
    </Hero>

    <!-- This is where all yours pages will be -->
    <nuxt />

    <Footer />

  </div>
</template>

<script>  
// Import Header component
import Header from '~/components/Header.vue'  
import Footer from '~/components/Footer.vue'  
import Hero from '~/components/Hero.vue'  

import { mapGetters } from 'vuex'

export default {
  data(){
    return {
      //declaring hero Obj to contain hero data
      hero: {
        title: "",
        subtitle: "",
        imgUrl: ""
      }
    }
  },

  components: {
    Header,
    Footer,
    Hero
  },

  //Getting getHero getter from hero.js and saving it to newHero
  computed: mapGetters({
    newHero: 'hero/getHero'
  }),

  //watching newHero to change and then updating this.hero Obj. This action will update the displayed data
  watch: {
    newHero: function (obj) {
      this.hero = {...this.hero, ...obj}
    }
  }
}
</script>  

Here I declare the variables and store than into Vuex Store:

<template>  
...
</template>

<script>  

export default {
  data() {
    return {
      hero: {
        title: "Awesome Static title",
        subtitle: "Awesome static subtitle"
      }
    }
  },

  //Saving the declared Hero to Vuex Store, then my default.vue will be able to get it through this.$store.getters  
  mounted() {
    this.$store.commit("hero/setData", this.hero);
  },
}
</script>  

At some pages the title are fetched from the database (GraphQL using Apollo). Then I did:

<template>
...
</template>

<script>
import getLojaInfo from '~/apollo/queries/loja/loja.gql'

export default {  
  //declaring data
  data() {
    return {
      lojas: Array,
      loading: 0,
      hero: {
        title: "",
        subtitle: "",
        imgUrl: ""
      }
    }
  },

  //making the query
  apollo: {
    lojas: {
      $loadingKey: 'loading',
      prefetch: true,
      query: getLojaInfo,
      variables () {
        return { slug: this.$route.params.singleLoja }
      },
      //it will wait for query result that and then populate this hero, it will update the hero title, subtitle and image
      result(ApolloQueryResult, key) {
        this.hero.title = ApolloQueryResult.data.lojas[0].name
        this.hero.subtitle = ApolloQueryResult.data.lojas[0].description
        this.hero.imgUrl = ApolloQueryResult.data.lojas[0].logo.url

      //then commit it to Vuex Store
        this.$store.commit("hero/setData", this.hero);

      }
    },
  },
}
</script>

Thank you all, I would appreciate contributions to my code.

Leave a comment