dword-design/nuxt-route-meta

Route meta remains empty with head() vs head{}

RobSteward opened this issue · 7 comments

I'm not 100% whether this was mentioned in one of the other issues.

Given my page files structure

head() {
    return {
      title: this.title,
      meta: [
        {
          breadcrumb: this.title,
          hid: this.title,
          name: this.title,
          content: `This page contains ${this.title} content`,
        },
      ],
    }
  },
  data() {
    return {
      title: 'Some title',
    }
  },

After installing and adding to nuxt.config.js like so

  modules: [
    '@nuxtjs/axios',
    '@nuxtjs/pwa',
    '@nuxtjs/firebase',
    'nuxt-route-meta',
  ],

Calling meta in my breadcrumb component like so results in an empty object:

console.log('Meta data is', this.$route.matched[i].meta)

image

Am I missing something? Could this be related to the difference between head as an object and head as a function? Given that I depend on the data() to be returned?

@RobSteward Yes the function is probably the problem. So, this module is mainly for accessing metadata a build time like when generating a sitemap or when dealing with the routes themselves. It won't work with dynamic data like metadata returned from a function (at least I have no idea how to do that). Interesting would be what your use case is when accessing this.$route.matched[i].meta. What are you trying to do?

I will look into that. As below will show I kinda depend on setting the meta info dynamically.

I'm building a breadcrumb component to use on the layout level across my different app areas (like tasks, reminders, notes...etc).
In the breadcrumb when a route includes and :id page I would like to use the subject/title of the task or reminder to display in the crumbs. So instead of what I currently have
Home > Reminders > 39jg082308hf (some reminder id I get get from route) > Edit
I would like it to be
Home > Reminders > Don't feed the trolls > Edit

I could access the store with the id from the path, then get the title ..etc.. but that just sounds very complicated - not really KISS. Any suggestions are welcome!

I think it depends on if you want to generate the breadcrumbs right from the route structure or provide breadcrumbs that are calculated per-page. For the latter I guess this module could work, also there are some examples where people take the matched route, extract infos from that and put them in the translation module.
https://gist.github.com/nilocoelhojunior/522c6695c46a851671edf88d8551a79a

For the latter, it maybe makes sense to create a computed variable that holds an array with the breadcrumb entries. Something like this but maybe with dynamic stuff like loading data from ids:
https://bootstrap-vue.org/docs/components/breadcrumb

Hope this helps!

Thanks @dword-design. I am actually using something similar based on the same initial idea from XXX:

Here's my full breadcrumb component:

<template>
  <div>
    <!-- {{ breadcrumbs }} <br /><br /> -->
    <v-breadcrumbs :items="breadcrumbs">
      <template v-slot:item="{ item }">
        <v-breadcrumbs-item
          :to="item.to"
          :disabled="item.disabled"
          nuxt
          exact
        >
          {{ item.text }}
        </v-breadcrumbs-item>
      </template>
      <template v-slot:divider v-if="breadcrumbs.length > 1">
        <v-icon>mdi-chevron-right</v-icon>
      </template>
    </v-breadcrumbs>
  </div>
</template>

<script>
export default {
  computed: {
    breadcrumbs: function () {
      let pathArray = this.$route.path.split('/')
      pathArray.shift()
      let breadcrumbs = pathArray.reduce((crumb, path, i, { length }) => {
        if (path) {
          crumb.push({
            disabled: i === length - 1 ? true : false,
            text:
              path
                .replace(/\/:[^/:]*$/, '')
                .substring(0, 1)
                .toUpperCase() +
              path
                .replace(/\/:[^/:]*$/, '')
                .substring(1)
                .toLowerCase(),
            to: crumb[i - 1]
              ? '/' + crumb[i - 1].path + '/' + path
              : '/' + path,
          })
        }
        // TODO pass item title to meta data to set actual item name rather than id from path
        // console.log('Meta data is', this.$route.matched[i].meta)
        return crumb
      }, [])
      breadcrumbs.splice(0, 0, {
        disabled: false,
        text: '🏠 Home',
        to: '/',
      })
      return breadcrumbs
    },
  },
}
</script>

What I am struggling with is passing data from my current page (like the edit page of an item) to the component that is part of a layout. Both the links you have mentioned focus on mostly on the path variable to contain all relevant information.

One way that I will try is to use fetch or asyncData to dispatch an action with the current name of the object to the store and then retrieve it in the breadcrumb component to use. Maybe that works, but as I had mentioned before, that does not sound KISS.

@RobSteward Yeah the ideas I'd have would be either to use a common layout, do the breadcrumb building there and pass it down to the breadcrumb component via props, or, if you need to instantiate the component several times, use a middleware to update a store value and query this one for each component and again pass it down via props.

Hi, the idea on passing the props is actually good! Didn't think of that. This could help me: https://stackoverflow.com/questions/62571970/nuxt-how-to-pass-data-from-page-to-layout.

Solutions suggest to simply use vuex with computed properties in the layout that are passed as a prop or called directly in the component (breadcrumbs in my case).

Thanks! We can lose this, I guess.

Yup sounds good!