Displaying application Breadcrumbs in Vue.js
Breadcrumbs are essential if your application has many nested screens. It allows users to keep track of their locations when they are navigating around the app.
Source code for this post is here.
In many frameworks, naive way of implementing it would be by adding breadcrumb metadata in the route definition in an array and then iterating it in every component which needs to show the crumbs. The problem with this approach is we are hardcoding the path and we can’t show crumbs for dynamic params.
If we are to do what I said just now in Vue.js, we could do it this way.
In the snippet above :moon
param belongs to the first child of the third route /saturn
. This param is determined at runtime and I can’t specify it’s crumb in the breadCrumb
property of it’s route definition.
The static crumbs defined above can be displayed by iterating $route.meta.breadCrumbs
array in any component.
Dynamic Breadcrumb component
vue-router
provides a $route
object which represents the state of the current active route. I feel this object provides us enough information to display the crumbs at runtime. The properties I’m interested in are $route.path
and $route.matched
.
$route.path
— A string that equals the path of the current route, always resolved as an absolute path. e.g."/foo/bar"
.
$route.matched
— An Array containing route records for all nested path segments of the current route. Route records are the copies of the objects in theroutes
configuration Array (and inchildren
Arrays).The Route Object —
vue-router
Alright, Lets get started. Say I have loaded a component with path /earth/moon
, I have added the text for the crumbs in the meta
property of my route definitions like below and I want the bread crumbs as Earth > Moon
.
The current absolute path for the component can be accessed through $route.path
and inside a component I can access it through this.$route.path
.
// this.$route.path will be equal to '/earth/moon'let pathArray = this.$route.path.split("/")// pathArray is now ["", "earth", "moon"]// we don't want the first item as it's empty
pathArray.shift()// pathArray is now ["earth", "moon"]
Now I need to access the breadCrumb
property from the meta
property of the component’s route definition, for this I will be using $route.matched
. For the component /earth/moon
the $route.matched
would contain two objects as it has matched two routes i.e. /earth
and /earth/moon.
0: {path: "/earth", regex: /^\/earth(?:\/(?=$))?$/i, components: {…}, instances: {…}, …}1: {path: "/earth/moon", regex: /^\/earth\/moon(?:\/(?=$))?$/i, components: {…}, instances: {…}, …}
These two objects are the copies of the objects in the routes
configuration Array of the /earth
and /earth/moon
routes.
I can assess breadCrumb
property for the /earth
component like this
this.$route.matched[0].meta.breadCrumb
and for /earth/moon
like this
this.$route.matched[1].meta.breadCrumb
Next I will create a new Array
of Objects
where each Object
will have property to
and text
for each item in the pathArray
. Each Object
in the Array
will represent a crumb. I will name this Array
as breadCrumbArray
.
Lately, I’m liking to write in Functional Programming style 🤓, so I will use reduce
method to simplify this Array
creation process.
In the above snippet path
property stores the string of the item in pathArray
as is, to
property will store path for the :to
property for the router-link
which will triggered when clicking the crumb. In the to
property we prefix the previous item’s path
if it exist else we assign the current item’s path
to it.
The resulting array of the reducer is assigned to breadcrumbs
variable and it will look like this.
[
{ "path": "earth", "to": "/earth", "text": "Earth" },
{ "path": "moon", "to": "/earth/moon", "text": "Moon" }
]
The last step would be to wrap the above logic in a vue component. I will use the breadcrumb
component of bootstrap-vue
to display the bread crumbs.
The final breadcrumb component will look like this
The above logic will also handle dynamic parms as we are picking up the constructed path from $route.path
. The crumb text for dynamic params will be the path
itself. You can see this at line 23
in the above snippet, I’m assigning the path
if the breadCrumb
property doesn’t exist.
Live demo demonstrating everything explained above is here.
Article Originally published on ZeoLearn
🤘🏻