Linking to a Specific Tab in Vuetify.js
Store the current tab in the URL, to navigate to it from anywhere else in the app
I would like to present to you a quick tip about working with the tabs component in Vuetify.js. I sometimes need to navigate to a specific tab in the application or want to share a direct tab link with a collaborator.
In order to achieve this, we need to store the information about the current tab in the URL in the browser address bar. A canonical solution involves using nested routes, but sometimes it’s an overkill to create a separate child page for each tab. Thankfully there’s a simpler approach that I quite often end up using.
TL;DR — go straight to the final code
Simple Tabs
First let’s look at a simple tabs component example:
<template>
...
<v-card>
<v-tabs v-model="tab" background-color="grey lighten-4">
<v-tab>
One
</v-tab>
<v-tab>
Two
</v-tab>
</v-tabs> <v-tabs-items :value="tab">
<v-tab-item>
<v-card-text>
This is ONE!<br>1111111111
</v-card-text>
</v-tab-item>
<v-tab-item>
<v-card-text>
This is TWO!<br>2222222222
</v-card-text>
</v-tab-item>
</v-tabs-items>
</v-card>
...
</template><script>
export default {
data: () => ({
tab: null
})
}
</script>
Note that we could also mix tabs with tab items in
<v-tabs>
component for simplicity, but I prefer to separate tabs from tab items for flexibility.
With the above code, the current tab is stored in the tab
variable as an ordinal number. The problem with using this number to identify a tab is that the order of tabs can change if we add any new ones in the future.
Named Tabs
Instead of distinguishing tabs by their number, we can use a descriptive name. To achieve this we need to specify a href
attribute on the tab and a value
attribute on the tab item:
<v-card>
<v-tabs v-model="tab" background-color="grey lighten-4">
<v-tab href="#one">
One
</v-tab>
<v-tab href="#two">
Two
</v-tab>
</v-tabs> <v-tabs-items :value="tab">
<v-tab-item value="one">
<v-card-text>
This is ONE!<br>1111111111
</v-card-text>
</v-tab-item>
<v-tab-item value="two">
<v-card-text>
This is TWO!<br>2222222222
</v-card-text>
</v-tab-item>
</v-tabs-items>
</v-card>
Note that we need to prepend the tab name with a hash symbol in the
href
attribute (e.g.href="#one"
), but not in thevalue
attribute.
Storing the Current Tab in the URL
In order to store the current tab in the URL, we will use a computed tab property with a setter. Let’s replace our data
with:
computed: {
tab: {
set (tab) {
this.$router.replace({ query: { ...this.$route.query, tab } })
},
get () {
return this.$route.query.tab
}
}
}
Note that we are calling
$router.replace()
instead of$router.push()
to avoid storing a visited tab in navigation history and to preserve the back-button functionality.
Now, when we visit the page for the first time, the URL will include the current tab as a query parameter. It will also update this parameter automatically every time we switch the tab.
One last thing — a button linking to a specific tab will simply look as follows:
<v-btn to="/page?tab=one">
Tab One
</v-btn>
Note that the button destination can be written as:
:to="{ path: '/', query: { tab: 'two' } }"
if you prefer the object syntax. The same will also work for router links.
And that’s it — a simple way of tab tracking in the URL. We will explore the more complex solution involving nested routes (aka child pages) in a follow-up article.
You can find a complete working code example for this article in this repository: