How to use router-link "to" prop on vuetify components? - vue.js

I have an avatar image, upon click I'd like to route to one of my paths. I understand I can do it with router-view, but also that vuetify inherits its properties.
What is missing?:
<div id="app">
<v-app>
<v-app-bar>
<v-toolbar-items>
<v-avatar to="'/profile'">
<v-img src="http://www.dumpaday.com/wp-content/uploads/2019/10/00-156-750x280.jpg"></v-img>
</v-avatar>
</v-toolbar-items>
</v-app-bar>
</v-app>
</div>
full example:
https://codepen.io/toit123/pen/GRRmpqq

v-avatar isn't a link abd doesn't support to so you have to wrap your image with a router link like:
<div id="app">
<v-app>
<v-app-bar>
<v-toolbar-items>
<router-link to="/profile">
<v-avatar>
<v-img src="http://www.dumpaday.com/wp-content/uploads/2019/10/00-156-750x280.jpg"></v-img>
</v-avatar>
</router-link>
</v-toolbar-items>
</v-app-bar>
</v-app>
</div>
Or you add a custom click event on the v-avatar and do the routing in a method like
<v-avatar #click="forward">
JS
methods: {
forward() {
this.$router.push("/profile")
}
}

Related

Vuetify v-spacer is not working with v-tabs

I need to place logo on left side of navbar and tabs on the right side. I use v-space to do it but it doesn't work. I checked - it works fine with v-btn but not with v-tabs. I use Vue 2 and Vuetify 2.6:
App.vue
<template>
<v-app>
<v-main>
<Navbar />
<router-view/>
</v-main>
</v-app>
</template>
Navbar.vue
<template>
<v-app-bar
app
dense
dark >
<v-img
alt="Vuetify Logo"
class="shrink mr-2"
contain
src="https://cdn.vuetifyjs.com/images/logos/vuetify-logo-dark.png"
transition="scale-transition"
width="40"
/>
<v-spacer></v-spacer>
<v-tabs>
<v-tab>Project</v-tab>
<v-tab>Users</v-tab>
<v-tab>Settings</v-tab>
</v-tabs>
</v-app-bar>
</template>
This is what I got:
I wanted menu (tabs) to be aligned to the right. Why v-spacer is not working here?
I also checked this topic https://github.com/nuxt-community/vuetify-module/issues/165 but it also does not solve the issue.
Check this codesandbox I made: https://codesandbox.io/s/stack-70115344-jzhii?file=/src/components/Navbar.vue
There's no need to use a v-spacer. You only need to set the right prop to the v-tabs component.
<v-tabs right>
<v-tab>Project</v-tab>
<v-tab>Users</v-tab>
<v-tab>Settings</v-tab>
</v-tabs>
Try <v-tabs right>
<template>
<v-app-bar
app
dense
dark >
<v-img
alt="Vuetify Logo"
class="shrink mr-2"
contain
src="https://cdn.vuetifyjs.com/images/logos/vuetify-logo-dark.png"
transition="scale-transition"
width="40"
/>
<v-tabs right>
<v-tab>Project</v-tab>
<v-tab>Users</v-tab>
<v-tab>Settings</v-tab>
</v-tabs>
</v-app-bar>
</template>

Vuetify v-date-picker formatting is wonky - how can I fix?

v-date-picker formatting is screwy. The popup is chopped off at the bottom and there's a transparent gutter on the right hand side. Is this a known bug? The popup seems to always be the width of the container. I removed all CSS and simplified the app to the test below.
<!-- the layout (admin.vue) -->
<template>
<v-app>
<v-main>
<Nuxt class="ma-2"/>
</v-main>
</v-app>
</template>
<!-- the page -->
<template>
<div>
<v-menu :close-on-content-click="true" :nudge-right="40" transition="scale-transition" offset-y>
<template v-slot:activator="{ on }">
<v-text-field label="Date listed" prepend-icon="mdi-calendar" :value="form.dateListed" v-on="on"/>
</template>
<v-date-picker v-model.lazy="form.dateListed" locale="en-us" header-color="primary" tabindex="0"/>
</v-menu>
</div>
</template>
<script>
export default {
layout: 'admin',
data() {
return {
form: {
},
}
},
}
</script>
enter image description here
You need to add min-width: auto to the v-menu like this:
<v-menu min-width="auto" v-model="menus.date">
...
</v-menu>

Vuetify routing: changing page content conundrum

I desire to see the content of uwc.vue upon clicking the "Let's GO" button (which is in App.vue).
But, the url changes & the content's of the screen still remain the same.
I am new to vue, I asked this question to the Vuetify community but it was ignored.
Thank you in advance.
router.js:
import Vue from 'vue';
import Router from 'vue-router';
import uwc from '../views/uwc';
Vue.use(Router);
export default new Router({
mode: 'history',
routes: [
{ path: '/', name: 'uwc', component: uwc},
]
});
App.vue
<template>
<v-app>
<v-container fluid>
<v-col class="d-flex mx-auto" >
<!-- UWC Card -->
<v-card class="mx-auto my-15" max-width="400" >
<v-img height="400px" class="image-fit" src="./img/UWC-logo.webp" ></v-img>
<v-divider class="mx-4"></v-divider>
<v-card-title>
<p class="text-break">
University of the Western Cape
</p>
</v-card-title>
<v-card-actions>
<router-link to="/views/uwc">
Let's GO
</router-link>
</v-card-actions>
</v-card>
</v-col>
</v-container>
</v-app>
</template>
<script>
export default {
name: 'app',
}
</script>
uwc.vue (the file I want to display on clicking the "Let's GO" button):
<template>
<v-app id="inspire">
<router-view></router-view>
<v-container fluid>
<v-row>
<template v-for="n in 4">
<v-col :key="n" class="mt-2" cols="12">
<strong> Category {{ n }} </strong>
</v-col>
<v-col v-for="j in 6" :key="`${n}${j}`" cols="6" md="2">
<v-sheet height="150"></v-sheet>
</v-col>
</template>
</v-row>
</v-container>
</v-app>
</template>
First of all, this isn't a 'Vuetify' question. Its a general routing question for VueJS.
Your primary problem is that you do not have a <router-view/> in your App.vue file. This is what renders the paths in your router.
App.vue
<template>
<div>
<router-view/>
</div>
</template>
Now if you visit the '/' path, you will see the contents of your uwc.vue file.
I also wanted to point out another error.
Your <router-link></router-link> tags refer to the path in your router file, not the path to the file is located in your folder structure.
You have:
<router-link to="views/uwc">
Should be:
<router-link to="/">
If you are continuing to struggle, create a brand new app using the [Vue CLI][1].
Then add the router using vue add router. It will give you a pretty solid example to work off of on your app.
[1]: https://cli.vuejs.org/guide/creating-a-project.html#vue-create

Create a route out of router in vue

I'm using a vuetify application, App.vue looks like this
<template>
<v-app class="grey lighten-4">
<nav>
<Header/>
</nav>
<section><NavigationBar/></section>
<v-content>
<router-view></router-view>
</v-content>
<Footer/>
</v-app>
</template>
This works perfectly. But I faced the situation, when I need to create an empty page, so I don't want load footer, header or bar. Is there any way to create a route for an empty page in this case?
Nested Routes
https://router.vuejs.org/guide/essentials/nested-routes.html
<template>
<v-app class="grey lighten-4">
<router-view>
<nav>
<Header/>
</nav>
<section><NavigationBar/></section>
<v-content>
<router-view></router-view>
</v-content>
<Footer/>
<router-view>
</v-app>
</template>

Is there a Vue or Vuetify component that does not render ANY output?

I have a custom navMenu component that I show twice on my page - once across the top, and once hidden in a v-navigation-drawer until the screen width gets small enough to show it:
<template>
<nav>
<v-app-bar app hide-on-scroll>
<template #extension v-if="$vuetify.breakpoint.smAndUp">
<v-container>
<v-row>
<v-spacer />
<navMenu :items="menuItems" />
<v-spacer />
</v-row>
</v-container>
</template>
<v-app-bar-nav-icon
#click="toggleDrawer()"
v-if="$vuetify.breakpoint.xs"
/>
<img id="logo"
alt="corporate logo"
src="#/assets/full_logo.svg"
width="200"
height="60"
/>
<v-spacer />
<h3 class="info--text headline">My Fancy Website</h3>
</v-app-bar>
<v-navigation-drawer app
v-model="drawer"
v-if="$vuetify.breakpoint.smAndDown">
<navMenu :items="menuItems" />
</v-navigation-drawer>
</nav>
</template>
NavMenu.vue
<template>
<v-col v-for="(item, index) in items" :key="index">
<div v-if="item.children">
<v-menu transition="slide-y-transition" bottom>
<template #activator="{ on }">
<v-btn text v-on="on">{{ item.label }}</v-btn>
</template>
<v-list>
<v-list-item
v-for="(child, j) in item.children"
:key="j"
router
:exact="child.exact"
:to="{ name: child.routeName }"
>
<v-list-item-title class="text-capitalize">
{{ child.label }}
</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</div>
<div v-else>
<v-btn text router :to="{ name: item.routeName }" :exact="item.exact">
{{ item.label }}
</v-btn>
</div>
</v-col>
</template>
...you may have noticed a fatal flaw in my component: you can't iterate on a root element! Simple enough, wrap it in a <div />, right? Wrong. Wrapping the contents of the template in a div really screws up the layout of the menu items - it renders them stacked vertically instead of horizontally - I think the CSS is looking for a direct child or something.
Is there some alternative element that I can use for the template to satisfy the "one root element" edict that doesn't render any output? Oh, and I tried using the <template /> element already - you can't use it as a root element.
You were so close to finding the answer...
Actually, you should put in a div container, but then just change the display property of the container so the items are still positioned horizontally:
NavMenu.vue
<template>
<div style="display: flex">
<v-col v-for="(item, index) in items" :key="index">
...
I updated your code below. Essentially, all you need to do is to move the entire <v-navigation-drawer> component into your NavMenu.vue file and add the additional drawer prop. Since the <v-navigation-drawer component doesn't actually do much on its own. The #input event listener is only so that you can have the parent component update the drawer value outside of the child component.
<template>
<nav>
<v-app-bar app hide-on-scroll>
<template #extension v-if="$vuetify.breakpoint.smAndUp">
<v-container>
<v-row>
<v-spacer />
<navMenu :items="menuItems" />
<v-spacer />
</v-row>
</v-container>
</template>
<v-app-bar-nav-icon
#click="toggleDrawer()"
v-if="$vuetify.breakpoint.xs"
/>
<img id="logo"
alt="corporate logo"
src="#/assets/full_logo.svg"
width="200"
height="60"
/>
<v-spacer />
<h3 class="info--text headline">My Fancy Website</h3>
</v-app-bar>
<navMenu
v-if="$vuetify.breakpoint.smAndDown"
:drawer="drawer"
:items="menuItems"
#navInput="toggleDrawer()"
/>
</nav>
</template>
NavMenu.vue
<template>
<v-navigation-drawer app :value="drawer" #input="$emit('navInput')>
<v-col v-for="(item, index) in items" :key="index">
<div v-if="item.children">
<v-menu transition="slide-y-transition" bottom>
<template #activator="{ on }">
<v-btn text v-on="on">{{ item.label }}</v-btn>
</template>
<v-list>
<v-list-item
v-for="(child, j) in item.children"
:key="j"
router
:exact="child.exact"
:to="{ name: child.routeName }"
>
<v-list-item-title class="text-capitalize">
{{ child.label }}
</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</div>
<div v-else>
<v-btn text router :to="{ name: item.routeName }" :exact="item.exact">
{{ item.label }}
</v-btn>
</div>
</v-col>
</v-navigation-drawer>
</template>
<script>
export default {
props: {
drawer: Boolean,
items: {
type: Array,
default: () => []
}
}
};
</script>