Reputation: 1141
I have a project in Vue.js and I am using Vuetify. I have a toolbar and navigation drawer. What I would like is when on desktop the drawer is open. If the user clicks the side-icon the drawer switches to mini.
If on md the drawer switches to mini. if the user clicks the side-icon the mini switches back to drawer
If on sm or lower the navigation drawer switches to temporary
I have most of the pieces but I am getting an error when I click the side-icon. Computed property 'mini' was assigned to but it has no setter.
Here is my code:
<v-toolbar
:clipped-left="$vuetify.breakpoint.mdAndUp"
:app="$vuetify.breakpoint.mdAndUp"
:fixed="$vuetify.breakpoint.mdAndUp"
flat
fixed
:scroll-toolbar-off-screen="$vuetify.breakpoint.smAndDown"
:scroll-threshold="50">
<v-toolbar-side-icon @click.stop="mini = !mini">
</v-toolbar-side-icon>
<v-toolbar-title class="text-uppercase">
<span class="font-weight-light">LOGO</span>
</v-toolbar-title>
<v-spacer></v-spacer>
<v-toolbar-items class="">
<v-btn icon v-for="item in menu" :key="item.icon">
<v-icon>{{item.icon}}</v-icon>
</v-btn>
</v-toolbar-items>
</v-toolbar>
<v-navigation-drawer
clipped
:mini-variant="mini"
v-model="drawer"
:permanent="$vuetify.breakpoint.mdOnly"
:temporary="$vuetify.breakpoint.smAndDown"
app
hide-overlay>
<v-list dense>
<v-list-tile
v-for="(item, index) in items"
:key="index"
>
<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-list>
</v-navigation-drawer>
I have created a codepen with what I have so far:
https://codepen.io/jsd219/pen/gJJMPQ
Upvotes: 2
Views: 11746
Reputation: 2778
The problem is that you are trying to modify the computed property mini
.
To mutate a computed property, you would need to provide a computed setter:
computed: {
mini: {
get() {
// get logic
},
set(value) {
// set logic
}
}
}
In your case, your computed property mini
returns true or false if based on $vuetify.breakpoint.mdAndDown
. You would need to include a new variable, something like overwriteBreakpoint
and use that in your setter.
data() => ({
overwriteBreakpoint: true
}),
computed: {
mini: {
get() {
return this.$vuetify.breakpoint.mdAndDown || this.overwriteBreakpoint;
},
set(value) {
this.overwriteBreakpoint = value;
}
}
}
Here's an example: https://codepen.io/dormenog/pen/MddbMY?editors=1011
Update:
To make this work on multiple screen sizes you'll need to come up with defined rules on when each prop of your nav bar should be true
or false
. This will become very messy, very quickly, and the benefit of the keeping track of the state is not really valuable because the screens will not change size in real time on the user's device.
I would advice separating the contents of your navbar into a component and wrap it with multiple <v-navigation-drawer />
that will only be rendered by vue if the screen size is correct. This can be achieved using v-if
and v-else
.
Upvotes: 0
Reputation: 90148
You're trying to assign a computed property to itself:
@click.stop="mini != mini"
You really don't want to do that. To find out why, you want to read on JS setters and getters.
If you want mini
to be the computed which determines if your <navigation-drawer>
is minified or not, use two separate placeholders for your info:
menuOpen
), initially defined in data()
, as false
and then overwritten by your @click.stop="menuOpen != menuOpen"
$vuetify.breakpoint.mdAndUp
. Call it mdAndUp
. So your mini
becomes:
mini() {
return !(this.mdAndUp|| this.menuOpen);
}
See it here.
Upvotes: 1