How can I Build Dynamic Breadcrumbs Component base on current Route/URL?

Viewed 908

I'm trying to build a Breadcrumbs component dynamically generating link base on my current URL


Ex.

http://localhost:8080/car/create

My Breadcrumbs should look like

Home > car > create


Ex.

http://localhost:8080/car/ford

My Breadcrumbs should look like

Home > car > ford


Ex.

http://localhost:8080/car/ford/raptor   

My Breadcrumbs should look like

Home > car > ford > raptor

How would one dynamically build sth like this ?


I have

<template lang="">
    <v-row>
            <v-breadcrumbs :items="links" class="black--text">
                <template v-slot:divider>
                    <v-icon>mdi-chevron-right</v-icon>
                </template>
            </v-breadcrumbs>
        </v-row>
</template>
<script>
export default {
    name: 'Breadcrumbs',
    props: {
        title: String
    },
    data() {
        return {
            links: [
                {
                    text: 'Home',
                    disabled: false,
                    href: '/'
                },
                {
                    text: this.title,
                    disabled: true,
                    href: 'breadcrumbs_link_2'
                }
            ]
        }
    }
}
</script>
2 Answers

You need to implement a computed property like the following:

const breadcrumb = Vue.component('breadcrumb', {
  template: '#breadcrumb',
  props: { title: String },
  computed: {
    links: function() {
      return [ 
        { text: 'Home', disabled: false, href: '/' }, 
        { text: this.title, disabled: true, href: 'breadcrumbs_link_2' },
        ...(
          (new URL(window.location.href))
            .pathname
            .split('/')
            .slice(1)
            .map(seg => ({ text: seg, disabled: false, href: seg }))
        )
      ]; 
    }
  }
});

new Vue({ el:"#app", vuetify: new Vuetify(), components: { breadcrumb } });
<script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script><link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/@mdi/font@4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet">

<template id="breadcrumb">
  <v-row>
    <v-breadcrumbs :items="links" class="black--text">
      <template v-slot:divider><v-icon>mdi-chevron-right</v-icon></template>
    </v-breadcrumbs>
  </v-row>
</template>

<v-app id="app">
  <breadcrumb title="title_1" />
</v-app>

This solution gives you the ability to customize the text on the crumbs via the vue router(other than relying on the path text which may not always be sufficient) and also allow to even capture url parameters.

in your router.js add an extra property to each object

{
          path: "bank-statement",
          component: StorageAccountList,
          name: "storage-accounts",
          meta: {
            title: "Bank Accounts ",
            resource: "bankAccounts",
            breadCrumb: "Bank & Cash accounts"
          }
        },

then in your computed of the main component that houses all others, add this

<v-breadcrumbs
        style="padding-top: 15px; padding-bottom: 0;"
        :items="crumbs"
      >
        <template v-slot:divider>
          <v-icon>mdi-chevron-right</v-icon>
        </template>
      </v-breadcrumbs>

computed: {
    
    crumbs: function() {
      let pathArray = this.$route.path.split("/");
      pathArray.shift();
      let itemsCount = pathArray.length;

      return pathArray.reduce((breadcrumbArray, path, idx) => {
        let count = idx + 2;
        breadcrumbArray.push({
          // to: {path:idx>1 ? "/" + breadcrumbArray[idx - 1].path + "/" : "/"+path },
          path: path,
          disabled: count > itemsCount,
          href: breadcrumbArray[idx - 1]
            ? "/" + breadcrumbArray[idx - 1].path + "/" + path
            : "/" + path,
          text:
            (this.$route.matched[idx] &&
              this.$route.matched[idx].meta.breadCrumb) ||
            path
        });
        return breadcrumbArray;
      }, []);
    }
  },
Related