8

I am using Vuetify and I can't seem to solve this issue. I have a <v-list> in my <v-navigation-drawer> which looks like this :

SideDash.vue component

<template>
    <v-navigation-drawer
        v-model="drawer" clipped
        :mini-variant.sync='mini'
        width=240 absolute permanent
    >
        <v-list
            flat dense nav class="py-1"
        >
            <v-list-item-group color='primary' mandatory>
                <v-list-item
                    v-for="item in items"
                    :key="item.title"
                    dense
                    router :to="item.route"
                >
                    <v-list-item-icon>
                        <v-icon>{{ item.icon }}</v-icon>
                    </v-list-item-icon>
                    <v-list-item-content>
                        <v-list-title>{{ item.title }}</v-list-title>
                    </v-list-item-content>

                </v-list-item>
            </v-list-item-group>
        </v-list>
    </v-navigation-drawer>
</template>


<script>
export default {
    data() {
        return {
            drawer: true,
            items: [
                {icon: 'mdi-speedometer', title:'Dashboard', route:'/dashboard'},
                {icon: 'mdi-tools', title:'Tools', route:'/tools'}
            ],
        }
        
    }
    
}
</script>

router/index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import Dashboard from '@/views/Dashboard.vue'
import Tools from '@/views/Tools.vue'


Vue.use(VueRouter)

const routes = [
  {
    path: '/dashboard',
    name: 'dashboard',
    component: Dashboard
  },
  {
    path: '/tools',
    name: 'tools',
    component: Tools
  }
]

const router = new VueRouter({
  mode: 'history',
  routes: routes
})

export default router

App.vue

<template>
  <v-app>
    <nav>
      <Navbar/>
    </nav>
    
    <v-content>
      <SideDash/>
    </v-content>
    
  </v-app>
</template>

<script>
import Navbar from './components/Navbar';
import SideDash from './components/SideDash'

export default {
  name: 'App',

  components: {
    Navbar,
    SideDash
  },

  data: () => ({

  }),
};
</script>

This is rather simple, and it worked well until I added the prop :to="item.route" to my v-list-item. This makes my list completly disappear. I end up with a navigation-drawer with nothing in it and I can't figure out why. What am I missing here ? Thanks for your help

PS: This might be helpful, but when I add <router-view></router-view> inside the <v-content></v-content> of my App.vue, I get a blank page, without even my navbar or nav-drawer. I feel that it might come from my router set up. I checked in my package.json and I have it

"vue-router": "^3.1.3"

EDIT

Well, I found the error... it's silly. In the file main.js the import router from './router' was commented such as router inside new Vue(...). I kept the code as it is displayed here and it worked.

Community
  • 1
  • 1
JrmDel
  • 390
  • 1
  • 4
  • 16

4 Answers4

8

Any suggestions as to why the :to method would work, but not the @click method?

Works

<v-list-item 
   :to="item.route"
   v-else
   :key="i"
   link
>

Doesn't

  <v-list-item 
    @click="$router({path: item.route})"
    v-else
    :key="i"
    link
  >
Half_Duplex
  • 5,102
  • 5
  • 42
  • 58
  • 1
    Indeed, I found out that the `@click` doesn't work. I tried to add the prop `router` to your `v-list-item` but then again it does not help. I am interested as well to know why it doesn't work – JrmDel May 04 '20 at 09:13
  • 2
    `$router({path: item.route})` did not work for me. I had to change it to `$router.push({path: item.route})` – Ben McCann Jan 14 '21 at 01:10
5

Finally, I got this worked.

<v-list-item :key="i" link @click="$router.push({ path: item.route })">
  <v-list-item-action>
    <v-icon>{{ item.icon }}</v-icon>
  </v-list-item-action>
  <v-list-item-content>
    <v-list-item-title class="grey--text">
      {{ item.text }}
    </v-list-item-title>
  </v-list-item-content>
</v-list-item>

source: https://router.vuejs.org/guide/essentials/navigation.html

they said: "clicking <router-link :to="..."> is the equivalent of calling router.push(...)."


edited: use @click="$router.push({ path: item.route }).catch(err => {}) if u don't wanna see "Error: Avoided redundant navigation to current location: "/about".

source: NavigationDuplicated Navigating to current location ("/search") is not allowed [vuejs]

acbetter
  • 188
  • 3
  • 9
2

The above code looks correct there is one small fix needs to be given in v-list item click event @click="$router({path: item.route})"

items: [
                {icon: 'mdi-speedometer', title:'Dashboard', route:'/dashboard'},
                {icon: 'mdi-tools', title:'Tools', route:'/tools'}
            ],


<template>
    <v-navigation-drawer
        v-model="drawer" clipped
        :mini-variant.sync='mini'
        width=240 absolute permanent
    >
        <v-list
            flat dense nav class="py-1"
        >
            <v-list-item-group color='primary' mandatory>
                <v-list-item
                    v-for="item in items"
                    :key="item.title"
                    dense
                    @click="$router({path: item.route})"
                >
                    <v-list-item-icon>
                        <v-icon>{{ item.icon }}</v-icon>
                    </v-list-item-icon>
                    <v-list-item-content>
                        <v-list-title>{{ item.title }}</v-list-title>
                    </v-list-item-content>

                </v-list-item>
            </v-list-item-group>
        </v-list>
    </v-navigation-drawer>
</template>
chans
  • 5,104
  • 16
  • 43
  • Thanks ! It made my list reappear ! How can I test if the routing works though ? The url is not changed when I click on a list-item, plus, when I add `` in the v-content of my App.vue, to check if it shows the desired page, I still get a blank page. – JrmDel Mar 05 '20 at 08:44
  • I've made changes to the answer, you don't need to remove '/' from your route it should be items: [ {icon: 'mdi-speedometer', title:'Dashboard', route:'/dashboard'}, {icon: 'mdi-tools', title:'Tools', route:'/tools'} ],, it will work as expected. Please let me know if that works – chans Mar 05 '20 at 09:01
  • I've tried with the '/' and it's the same result. I've checked in the dev tools' console and I get the error `'route is undefined'`. All those errors could come from my router in the end ? – JrmDel Mar 05 '20 at 09:08
  • Well, I found the error... it's silly, the `import router from './router'` was commented such as `router` inside `new Vue(...)` in the file **main.js**. Thank you so much for your help and sorry for this mistake – JrmDel Mar 05 '20 at 09:26
  • 2
    What is the difference between `@click="$router({path: item.route})"` and `:to="item.route"` – Half_Duplex May 03 '20 at 02:51
  • 1
    @Half_Duplex, when you use @click="$router({path: item.route})" event handler, it just displayed the button as html and click event programatically navigates to different page with the help of this.$router from vue-router lib. But when you use :to="item.route", it creates a hyperlink tag and when user clicks, it navigates to different page. Let me know if have anymore questions – chans May 03 '20 at 05:07
  • So sounds like `@click` would be the preferred option as to use router? – Half_Duplex May 03 '20 at 16:31
  • Yes, based on your requirement, you can use any of the one – chans May 04 '20 at 04:51
1

Just a little sidenote. If you use

{icon: 'mdi-speedometer', title:'Dashboard', route:'/dashboard'},

in the drawer, you will run into an error if you e.g. want to put an optional part of the index path

...
  {
    path: '/:extra?',
    name: 'Index',
    component: Index,
  },
...

The links will not work anymore since you just use "links" and not the real router anymore. (router-link will still work).

Its is better to use the following syntax:

{icon: 'mdi-speedometer', title:'Dashboard', route:({name: 'dashboard'})},

This way you use the router from vuejs and you will not receive any problems with "direct" links.

Chris
  • 415
  • 5
  • 19