I am using vuetify.js and trying to create a component which can be reusable across the application. Although its working absolutely fine, but I am not sure if it's the correct way.
I am creating a navigation drawer component which has the same menu options all the time but it can be opened from UI elements.
Below is the code.
// NavigationBar.vue
<template>
<v-navigation-drawer
temporary
v-model="drawerFlag"
light
overflow
fixed
>
<v-list>
<v-list-tile>
<v-list-tile-action @click.stop="toggleDrawer()">
<v-btn icon>
<v-icon>close</v-icon>
</v-btn>
</v-list-tile-action>
</v-list-tile>
</v-list>
<v-list class="pt-0">
<template v-for="item in items">
<v-list-tile :key="item.title" :to="item.link">
<v-list-tile-action>
<v-icon>{{ item.icon }}</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>{{ item.title }}</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
<v-divider></v-divider>
</template>
</v-list>
</v-navigation-drawer>
</template>
<script>
export default {
props: ['drawer'],
data() {
return {
items: [
{ title: 'Home', icon: 'home', link: '/home'},
{ title: 'History', icon: 'history', link: '/history' },
{ title: 'Wallet', icon: 'account_balance_wallet', link: '/wallet' },
{ title: 'My Profile', icon: 'person', link: '/profile' },
{ title: 'Settings', icon: 'settings', link: '/settings' },
{ title: 'About', icon: 'error', link: '/about' },
{ title: 'Logout', icon: 'power_settings_new', link: '/logout' },
]
};
},
computed: {
drawerFlag: {
get: function() {
return this.drawer
},
set: function() {
}
}
},
methods: {
toggleDrawer: function() {
this.$emit('emitToggleDrawer');
}
}
}
</script>
//Home.vue
<template>
<div class="full-screen">
<navigation-bar :drawer="drawer" v-on:emitToggleDrawer="toggleDrawer"></navigation-bar>
<v-btn icon class="mt-3 fixed-position" @click.stop="drawer = !drawer">
<v-icon>menu</v-icon>
</v-btn>
</div>
</template>
<script>
export default {
name: 'home',
data() {
return {
drawer: null
};
},
computed: {
user() {
return this.$store.getters.user;
}
},
methods: {
toggleDrawer: function () {
this.drawer = !this.drawer;
}
}
};
</script>
In the above code..
In parent component, I have button to open navigation-drawer and the state of the navigation drawer is maintained in the parent component called "drawer". Then, I am passing "drawer" as a prop to child component and a method to trigger an event from child component to parent component called "emitToggleDrawer".
In child component, I am using vuetify.js navigation-drawer which takes v-model="drawerFlag", where drawerFlag is a computed property. When i tried to use v-model="drawer" i.e. binding to the prop I was getting an error. Then we can close the navigation drawer by clicking an element inside the navigation-drawer. To achieve that, I am calling a method of the component which later on emits an event which is listened by parent component.
To let our component support v-model two-way binding, the component needs to accept a value prop and emit an input event. To support v-model , the component accepts a value prop and emits an input event.
The v-bind directive is a Vuejs directive used to bind one or more attributes, or a component prop to an element. If that attribute is binded to our data defined in Vuejs instance then dynamically changes can be observed as data changes.
In simple words v-model is for two way bindings means: if you change input value, the bound data will be changed and vice versa. but v-bind:value is called one way binding that means: you can change input value by changing bound data but you can't change bound data by changing input value through the element.
The v-model directive makes two-way binding between a form input and app state very easy to implement. One can bind a form input element and make it change the Vue data property when the content of the field changes.
I solved it like this:
App.vue
<my-drawer ref="drawer"></my-drawer>
<my-header @toggle-drawer="$refs.drawer.drawer = !$refs.drawer.drawer"></my-header>
MyDrawer.vue
<v-navigation-drawer v-model="drawer">
...
data() {
drawer: true
}
MyHeader.vue
<v-toolbar-side-icon @click.stop="$emit('toggle-drawer')"></v-toolbar-side-icon>
v-model="drawer"
on custom drawer component so it can properly work on all screen sizes.
Thus we need to change it's value from parent (or sibling) somehow also, that's why I'm using ref on drawer component.
Maybe instead of changing $refs.drawer.drawer
data I could call drawers functions instead. I'm not sure what would be better approach. But this was the only simple solution that worked for me on all screen sizes.
So in my case, I'm changing drawer state only from header, but I think you can use this and fit according to your needs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With