I am a new programmer and trying to make a non-toggling side bar, like admin page.
The router-view doesnt display on the right side of the page.
I know that I don't have a href link for each of the navigation list, where and how can I do that?
also, is the Apps causing conflict with the sellingSummary page?
and am I inserting the router-view in the wrong place?
I need help, thank you !!!!
image
<template>
<div>
<v-app id="inspire">
<v-navigation-drawer
stateless
value="true"
>
<v-list>
<v-list-group
no-action
prepend-icon="account_circle"
value="true"
>
<v-list-tile slot="activator">
<v-list-tile-title>admins</v-list-tile-title>
</v-list-tile>
<v-list-tile
v-for="(admin, i) in admins"
:key="i"
#click=""
>
<v-list-tile-title v-text="admin[0]"></v-list-tile-title>
<v-list-tile-action>
<v-icon v-text="admin[1]"></v-icon>
</v-list-tile-action>
</v-list-tile>
</v-list-group>
</v-list>
</v-navigation-drawer>
<div>
<router-view></router-view>
</div>
</v-app>
</div>
</template>
<script>
export default {
data() {
return {
admins: [
['Management', 'people_outline'],
['Settings', 'settings']
]
}
}
}
</script>
./router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import AppS from '#/components/SellingPage/AppS'
import sellingSummary from '#/components/SellingPage/subPage/sellingSummary'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/SellingPage',
name: 'AppS',
component: AppS
},
{
path: '/SellingPage',
name: 'sellingSummary',
component: sellingSummary
}
]
})
./components/SellingPage/subPage/sellingSummary
<template>
<div>
<p>Hi, first</p>
</div>
</template>
./components/SellingPage/AppS
<template>
<div>
<app-header></app-header>
<v-card>
<app-selling>
</app-selling>
</v-card>
</div>
</template>
<script>
import Header from '../Header.vue';
import Selling from './Selling.vue';
export default {
components: {
'app-header': Header,
'app-selling': Selling
}
}
</script>
<v-navigation-drawer
disable-route-watcher
enable-resize-watcher
:clipped="clipped"
v-model="sideNav"
dark
app
>
try this
For starters, you can't have two routes in your router configured for different components. The Router will only use the first entry.
In your component Vue file add the following property in the data property
drawer: true,
Example:
export default {
data: () => ({
drawer: true
})
}
The Navigation drawer has an item data property which can be used to loop through existing menu items.
In some of the properties, you can add a path attribute directing to an existing path on the router when that menu item is pressed.
Here is an example:
https://codepen.io/wernerm/pen/rzqqbR
Related
Currently when using transition in Vue I'm facing the problem that some of the components on the page disappear instantly whereas the rest fade out normally with the whole page.
This is my transition set up as minimal reproducible example, is working here Codepen
You can see when switching from Home route to any other route the button disappears instantly while the rest of the view disappears according to the fade properties set using css (and vue transitions).
// https://github.com/groloop/vuejs-2-series
Vue.use(Vuetify);
Vue.use(VueRouter);
var Home = {
template: '<div> <h2>Home</h2> <v-tooltip left> <template v-slot:activator="{ on }"> <v-btn color="primary" dark v-on="on">Left</v-btn> </template> <span>Left tooltip</span> </v-tooltip> </div>'
}
var AboutUs = {
template: '<h2>About Us</h2>'
}
var Contact = {
template: '<h2>Contact</h2>'
}
var NotFound = {
template: '<h2>Not Found</h2>'
}
var router = new VueRouter({
history: false,
routes: [
{ path: '/', name: 'home', component: Home },
{ path: '/about-us', name: 'about-us', component: AboutUs },
{ path: '/contact', name: 'contact', component: Contact },
{ path: '*', name: 'not-found', component: NotFound }
],
});
new Vue({
el: '#app',
router: router
});
.fade-enter-active,
.fade-leave-active {
transition-duration: 0.5s;
transition-property: opacity;
transition-timing-function: ease-in;
}
.fade-enter-active {
transition-delay: .5s;
}
.fade-enter,
.fade-leave-active {
opacity: 0
}
<link href="https://unpkg.com/vuetify#1.5.16/dist/vuetify.min.css" rel="stylesheet"/>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<script src="https://unpkg.com/vuetify#1.5.16/dist/vuetify.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.10/vue.js"></script>
<div id="app">
<v-toolbar>
<v-toolbar-title>TEST</v-toolbar-title>
<v-spacer></v-spacer>
<v-toolbar-items>
<v-btn flat href="#/">Home</v-btn>
<v-btn flat href='#/about-us'>About us</v-btn>
<v-btn flat href='#/contact'>Contact</v-btn>
<v-btn flat href='#/test'>Test</v-btn>
</v-toolbar-items>
</v-toolbar>
<transition name="fade" mode="out-in">
<router-view></router-view>
</transition>
</div>
That's probably due to how v-tooltip works internally. You can see that if you take the button component outside of the template slot in the v-tooltip component, transition works properly.
The v-tooltip component might have a destroy lifecycle hook that simply destroys the rendered DOM node, which can cause issues. A workaround will be to keep the <router-view> alive:
<transition name="fade" mode="out-in">
<keep-alive>
<router-view></router-view>
</keep-alive>
</transition>
However, this might not be desirable, especially if you have very heavy components used by the router, or if you have a lot of views to be kept alive:
Solution 1: Cap the max number of components to keep alive
Since you are only concerned with the fading out of the last destroyed component, you can use the max attribute on the <keep-alive> wrapper so that you only keep the last destroyed element. Something like this will work:
<transition name="fade" mode="out-in">
<keep-alive v-bind:max="2">
<router-view></router-view>
</keep-alive>
</transition>
Solution 2: Explicitly include components that need to be kept alive
Alternatively, you can selectively keep the components with <v-tooltip> alive. In your example, only the Home component is having a problem, so you can give it a name:
var Home = {
template: '<div> <h2>Home</h2> <v-tooltip> <template v-slot:activator="{ on }"> <v-btn color="primary" dark v-on="on">Left</v-btn> </template> <span>Left tooltip</span> </v-tooltip> </div>',
name: 'Home'
}
And then dynamically bind an array to the include attribute on the <keep-alive> component:
<transition name="fade" mode="out-in">
<keep-alive :include="componentsToKeepAlive">
<router-view></router-view>
</keep-alive>
</transition>
In your JS:
new Vue({
el: '#app',
router: router,
data: {
componentsToKeepAlive: ['Home']
}
});
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.
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
>
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]
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>
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.
I'm simply trying to use a child component in a Nuxt/Composition API/TypeScript project using Vuetify. I've tried including the component before the setup method, but when I view the source I only see <!----> where the child component data should be.
This is the layouts/default.vue layout that should be displaying the "nested" component.
<template>
<v-app>
<v-app-bar clipped-left app color="indigo darken-2" />
<v-content>
<nuxt />
</v-content>
<v-bottom-navigation
v-model="bottomNav"
color="indigo darken-2"
absolute
class="hidden-sm-and-up"
>
<v-btn
value="search"
#click="dialog=true"
>
<span>Search</span>
<v-icon>mdi-magnify</v-icon>
</v-btn>
</v-bottom-navigation>
<v-dialog v-model="dialog">
<ListFilter
#closeDialog="closeDialog"
/>
</v-dialog>
</v-app>
</template>
<script lang="ts">
import { createComponent, ref } from '#vue/composition-api'
import ListFilter from '~/components/ListFilter.vue'
export default createComponent({
components: { ListFilter },
setup() {
const bottomNav = ref<string>()
const dialog = ref<boolean>(false)
const closeDialog = () => {
dialog.value = false
bottomNav.value = ''
}
return {
bottomNav,
dialog,
closeDialog
}
}
})
</script>
Here is the sample contents of the components/ListFilter.vue component to be nested, the contents of which matter little.
<template>
<v-card>
<v-card-title>
Search
</v-card-title>
<v-card-text>
Test Text
</v-card-text>
<v-card-actions>
<v-btn
#click="closeDialog"
>
Close
</v-btn>
</v-card-actions>
</v-card>
</template>
<script lang="ts">
import { createComponent } from '#vue/composition-api'
export default createComponent({
setup(_, { emit }) {
const closeDialog = () => {
emit('closeDialog')
}
return closeDialog
}
})
</script>
Problem is return closeDialog in setup function of ListFilter component. If you return a function from setup(), Vue expects it is a render function. Try return { closeDialog } instead...
So I've been following the first example on how to create a dropdown menu on Vuetify. I basically copy pasted the entire code to ensure it was done right and added the necessary variables referenced in that example.
The problem I have is that the v-menu and everything within that tag doesn't show up at all. The menu I have for example is using v-btn, and it's visible as long as it's outside the v-menu tag. 'npm run build' and chrome debugger doesn't generate any errors either. I can use other Vuetify components but v-menu doesn't behave as documented...
Any help would be much appreciated.
I managed to make it work.
It is strongly advised to use vue-cli when you create vue projects.
I did the following in the command line:
$> yarn global add #vue/cli
$> vue create vuetify
$> yarn add vuetify
I added Vuetify in main.js:
import Vue from 'vue'
import App from './App.vue'
import Vuetify from 'vuetify'
Vue.config.productionTip = false
Vue.use(Vuetify)
new Vue({
render: h => h(App),
}).$mount('#app')
Then I replaced the content in components\HelloWorld.vue with the example:
<template>
<div class="text-xs-center">
<v-menu offset-y>
<template v-slot:activator="{ on }">
<v-btn
color="primary"
dark
v-on="on"
>
Dropdown
</v-btn>
</template>
<v-list>
<v-list-tile
v-for="(item, index) in items"
:key="index"
#click="test"
>
<v-list-tile-title>{{ item.title }}</v-list-tile-title>
</v-list-tile>
</v-list>
</v-menu>
</div>
</template>
<script>
export default {
data: () => ({
items: [
{ title: 'Click Me' },
{ title: 'Click Me' },
{ title: 'Click Me' },
{ title: 'Click Me 2' }
]
}),
methods: {
test() {
}
}
}
</script>
Then run yarn serve
And the dropdown button behaves as expected, minus the css.
I have created a Sidebar component using Vuetify's navigation drawer. The code looks something like this:
<template>
<v-navigation-drawer persistent clipped v-model="isVisible" fixed app>
<!-- content of the sidebar goes here -->
</v-navigation-drawer>
</template>
<script>
export default {
name: 'Sidebar',
props: {
visible: Boolean,
},
data() {
return {
isVisible: this.visible,
};
},
}
</script>
Please note that I am duplicating the visible prop with the isVisible data. I tried using the prop directly in the v-model but every time the sidebar closed, I would get a warning in the console about changing props directly, as they would be overwritten when the parent re-renders.
In the parent view, I have a button on the toolbar that is supposed to change icon depending on the visibility of the toolbar.
<template>
<v-container fluid>
<sidebar :visible="sidebarVisible"/>
<v-toolbar app :clipped-left="true">
<v-btn icon #click.stop="sidebarVisible = !sidebarVisible">
<v-icon v-html="sidebarVisible ? 'chevron_right' : 'chevron_left'"/>
</v-btn>
</v-toolbar>
<v-content>
<router-view/>
</v-content>
<v-footer :fixed="fixed" app>
<span>© 2017</span>
</v-footer>
</v-container>
</template>
<script>
import Sidebar from '#/components/Sidebar.vue';
export default {
name: 'MainView',
data() {
return {
sidebarVisible: false,
fixed: false,
title: 'Title',
};
},
components: {
Sidebar,
},
};
</script>
The problem I have is that if I close the sidebar by clicking outside of it, the icon of the button on the toolbar does not change to chevron-left. Moreover, in order to bring the sidebar back, I need to click on the button twice.
Clearly this is because the sidebarVisible data in the main view is not updated when the sidebar closes. How do I make sure that sidebarVisible is updated when the sidebar closes?
I am use next construction...
in my component
<template>
<v-navigation-drawer v-model="localDrawer"></v-navigation-drawer>
</template>
...
<script>
export default {
props: { value: { type: Boolean } },
data: () => ({
localDrawer: this.value
}),
watch: {
value: function() {
this.localDrawer = this.value
},
localDrawer: function() {
this.$emit('input', this.localDrawer)
}
}
}
</script>
in parent layer
<app-drawer v-model="drawer"></app-drawer>
it's work for me
Use v-bind:value or :value to bind the drawer value from props.
Child component:
<template>
<v-navigation-drawer v-bind:value="drawer"></v-navigation-drawer>
</template>
<script>
export default {
props : ['drawer']
}
</script>
Parent component:
<template>
<app-side-bar :drawer="drawer"/>
<v-app-bar app clipped-left>
<v-app-bar-nav-icon #click.stop="drawer = !drawer"></v-app-bar-nav-icon>
</v-app-bar>
</template>
Vuetify navigation drawer issue fix:
Reset your browser window to default 100%
Here is the code,
Template:
<nav>
<v-toolbar flat app>
<v-toolbar-side-icon class="grey--text" #click="toggle"></v-toolbar-side-icon>
<v-toolbar-title class="text-uppercase grey--text">
<span class="font-weight-light">Repo</span>
<span>hub</span>
</v-toolbar-title>
<v-spacer></v-spacer>
<v-btn flat color="grey">
<span>Sign Out</span>
<v-icon right>exit_to_app</v-icon>
</v-btn>
</v-toolbar>
<v-navigation-drawer app v-model="drawer" class="indigo">
<p>test</p>
</v-navigation-drawer>
</nav>
Script:
export default {
data() {
return {
drawer: false
};
},
methods:{
toggle(){
this.drawer = !this.drawer;
}
}
};