diff --git a/.changeset/tiny-bees-crash.md b/.changeset/tiny-bees-crash.md
new file mode 100644
index 000000000..cb572d0b9
--- /dev/null
+++ b/.changeset/tiny-bees-crash.md
@@ -0,0 +1,9 @@
+---
+"druxt-breadcrumb": minor
+---
+
+feat(#433): Added path prop to DruxtBreadcrumb component.
+
+```vue
+
+```
diff --git a/packages/breadcrumb/src/components/DruxtBreadcrumb.vue b/packages/breadcrumb/src/components/DruxtBreadcrumb.vue
index 414763c5b..8c7041bee 100644
--- a/packages/breadcrumb/src/components/DruxtBreadcrumb.vue
+++ b/packages/breadcrumb/src/components/DruxtBreadcrumb.vue
@@ -3,10 +3,14 @@ import DruxtModule from 'druxt/dist/components/DruxtModule.vue'
import { mapActions, mapState } from 'vuex'
/**
- * Renders a list of breacrumbs based on the active route.
+ * The DruxtBreadcrumb component renders a list of breadcrumbs based on the
+ * active route.
*
* @example @lang vue
*
+ *
+ * @example @lang vue
+ *
*/
export default {
name: 'DruxtBreadcrumb',
@@ -26,6 +30,21 @@ export default {
home: {
type: Boolean,
default: true
+ },
+
+ /**
+ * The Decoupled router path.
+ *
+ * If not set, the Vue router value will be used instead.
+ *
+ * @type {string}
+ *
+ * @example @lang vue
+ *
+ */
+ path: {
+ type: String,
+ default: ''
}
},
@@ -57,26 +76,34 @@ export default {
* Fetch Crumbs
*/
async fetchCrumbs() {
- // If there is no route, stop here.
- if (!this.route || !Object.keys(this.route).length) return
+ const path = this.path || this.$route.path
+ let route = this.route
+ if (this.path && path !== this.$route.path) {
+ route = await this.getRoute(path)
+ }
+
+ // If there is no route, throw an error.
+ if (!route || !Object.keys(route).length) {
+ throw new Error('No route data available.')
+ }
// If we are at the root and don't want a home crumb, stop here.
- if (this.$route.path === '/' && !this.home) return
+ if (path === '/' && !this.home) return
// Current route crumb.
const crumbs = []
- if (this.route.label) {
- crumbs.push({ text: this.route.label })
+ if (route.label) {
+ crumbs.push({ text: route.label })
}
// If we are at the root of the site, stop here.
- if (this.$route.path === '/') {
+ if (path === '/') {
this.model = crumbs
return
}
// Add crumbs for route parents.
- const paths = this.$route.path.split('/').filter(String)
+ const paths = path.split('/').filter(String)
paths.pop()
while (paths.length > 0) {
const to = '/' + paths.join('/')
diff --git a/packages/breadcrumb/test/components/DruxtBreadcrumb.test.js b/packages/breadcrumb/test/components/DruxtBreadcrumb.test.js
index d3fa6e900..846145171 100644
--- a/packages/breadcrumb/test/components/DruxtBreadcrumb.test.js
+++ b/packages/breadcrumb/test/components/DruxtBreadcrumb.test.js
@@ -4,6 +4,7 @@ import Vuex from 'vuex'
import { DruxtRouterStore } from '../../../router/src'
import DruxtBreadcrumb from '../../src/components/DruxtBreadcrumb.vue'
+import DruxtDebug from '../../../druxt/src/components/DruxtDebug.vue'
// Setup local vue instance.
const localVue = createLocalVue()
@@ -35,7 +36,9 @@ const mountComponent = ({ path, routes, propsData, options }) => {
store.commit('druxtRouter/setRoute', path)
}
- return shallowMount(DruxtBreadcrumb, { store, localVue, mocks, propsData, ...options })
+ const components = { DruxtDebug }
+
+ return shallowMount(DruxtBreadcrumb, { components, store, localVue, mocks, propsData, ...options })
}
describe('DruxtBreadcrumb', () => {
@@ -86,7 +89,10 @@ describe('DruxtBreadcrumb', () => {
})
test('level 2', async () => {
- const wrapper = mountComponent({ path: '/level-1/level-2', routes: ['/', '/level-1', '/level-1/level-2'] })
+ const wrapper = mountComponent({
+ path: '/level-1/level-2',
+ routes: ['/', '/level-1', '/level-1/level-2']
+ })
await wrapper.vm.$options.fetch.call(wrapper.vm)
expect(wrapper.vm.route).toStrictEqual({
@@ -99,6 +105,24 @@ describe('DruxtBreadcrumb', () => {
expect(wrapper.html()).toMatchSnapshot()
})
+ test('manual path', async () => {
+ const wrapper = mountComponent({
+ path: undefined,
+ propsData: {
+ path: '/level-1/level-2',
+ },
+ routes: ['/', '/level-1', '/level-1/level-2']
+ })
+ await wrapper.vm.$options.fetch.call(wrapper.vm)
+
+ expect(wrapper.vm.route).toStrictEqual({})
+
+ expect(wrapper.vm.crumbs).toHaveLength(3)
+ expect(wrapper.vm.crumbs[0].to).toBe('/')
+
+ expect(wrapper.html()).toMatchSnapshot()
+ })
+
test('missing parent', async () => {
const wrapper = mountComponent({ path: '/level-1/level-2', routes: ['/', '/level-1/level-2'] })
await wrapper.vm.$options.fetch.call(wrapper.vm)
diff --git a/packages/breadcrumb/test/components/__snapshots__/DruxtBreadcrumb.test.js.snap b/packages/breadcrumb/test/components/__snapshots__/DruxtBreadcrumb.test.js.snap
index 8bf28b87f..441dda19d 100644
--- a/packages/breadcrumb/test/components/__snapshots__/DruxtBreadcrumb.test.js.snap
+++ b/packages/breadcrumb/test/components/__snapshots__/DruxtBreadcrumb.test.js.snap
@@ -2,7 +2,7 @@
exports[`DruxtBreadcrumb 404 route 1`] = `
"
-
+
"
`;
@@ -18,6 +18,12 @@ exports[`DruxtBreadcrumb level 2 1`] = `
"
`;
+exports[`DruxtBreadcrumb manual path 1`] = `
+"
+
+
"
+`;
+
exports[`DruxtBreadcrumb missing parent 1`] = `
"