I am trying to work on the context menu for Vue3. I want to show the list of items under the v-menu by right-clicking on a dropdown button. I am working on this link as a reference but when I tried to do the same in my Vue3 file, It gives me an error like this-
Can anyone suggest what am I doing wrong? Here is the code-
<v-menu offset-y>
<template v-slot:activator="{ props }">
<v-btn
color="primary"
dark
v-bind="props"
#contextmenu.prevent="props.click"
>
Dropdown
</v-btn>
</template>
<v-list>
<v-list-item
v-for="(item, index) in menuClick"
:key="index"
#click=""
>
<v-list-item-title>{{ item.title }}</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
I couldn't discover any context menu event in Vue3's doc and Vuetify's menu API. Although, I have an alternative in my mind that can do this job. You can utilize the .right modifier sync with v-model to open the menu with the right click of a button.
Here is the strategy-
Use v-model to control the v-menu toggling status.
On the right-click, set the v-model to true so the menu will be open.
On the left-click (default) set the v-model to false. (Do this step only if you don't want to open the menu on the default click.)
Here is a functioning demo-
const { createApp } = Vue
const { createVuetify } = Vuetify
const vuetify = createVuetify()
const app = createApp({
data: () => ({
menu: false,
items: [
{ title: 'Click Me' },
{ title: 'Click Me' },
{ title: 'Click Me' },
{ title: 'Click Me 2' },
],
}),
}).use(vuetify).mount('#app')
<script src="https://unpkg.com/vue#3/dist/vue.global.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#3.1.2/dist/vuetify.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vuetify#3.1.2/dist/vuetify.min.css">
<div id="app">
<v-app>
<div class="d-flex justify-space-around mb-5 font-weight-bold">
I will open only with the right-click.
</div>
<div class="d-flex justify-space-around">
<v-menu v-model="menu">
<template v-slot:activator="{ props }">
<v-btn
color="primary"
v-bind="props"
#click.left.prevent="menu = false"
#click.right.prevent="menu = true"
>
Dropdown
</v-btn>
</template>
<v-list>
<v-list-item
v-for="(item, index) in items"
:key="index"
:value="index"
>
<v-list-item-title>{{ item.title }}</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</div>
</v-app>
</div>
Related
I'm trying to make a custom v-autocomplete using v-text-field and v-menu.
What confuses me is that v-menu closes when you click on the v-text-field again. The first click on the v-text field opens the v-menu, and the second click closes it. I couldn't find any property that turns off toggle mode.
Although, if you look at the html markup, v-menu is used in the v-select and v-autocomplete components, which close when you click on the content or outside the menu.
Codepen
<template>
<div id="app">
<v-app id="inspire">
<div class="text-center">
<v-main>
<v-container>
<v-row>
<v-col cols="3">
<v-menu bottom offset-y max-height="304px">
<template v-slot:activator="{ on, attrs }">
<v-text-field v-model="model && model.title"
dense color="primary"
v-bind="attrs" v-on="on"
label="Choose" outlined>
</v-text-field>
</template>
<v-list dense>
<v-list-item-group v-model="model"
color="primary">
<v-list-item v-for="(item, index) in items"
:key="item.id" :value="item"
dense>
<v-list-item-title>{{ item.title }}</v-list-item-title>
</v-list-item>
</v-list-item-group>
</v-list>
</v-menu>
</v-col>
</v-row>
</v-container>
</v-main>
</div>
</v-app>
</div>
</template>
<script>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
items: [
{id:1, title: 'Click Me 1' },
{id:2, title: 'Click Me 2' },
{id:3, title: 'Click Me 3' },
{id:4, title: 'Click Me 4' },
],
model: null
}),
})
</script>
I have a v-menu which contains a v-list with a custom component.
<v-toolbar class="transparent">
<v-menu offset-y>
<template v-slot:activator="{ on, attrs }">
<v-btn v-bind="attrs" v-on="on">
<span><v-icon>mdi-menu</v-icon></span>
</v-btn>
</template>
<v-list>
<AdminAgentList/>
</v-list>
</v-menu>
... more ...
That component is a dialog which defines a v-list-item to slot into the v-list in the v-menu.
<template>
<div> <!-- Agent List -->
<v-dialog v-model="agentList_dlgOpen" persistent max-width="40%" #keydown.esc="agentList_dlgOpen = false">
<template v-slot:activator="{ on, attrs }">
<v-list-item v-bind="attrs" v-on="on">
<v-list-item-title><v-icon>mdi-account-multiple</v-icon> Agent List</v-list-item-title>
</v-list-item>
</template>
<v-card>
<v-card-title>Agent List Maintenance</v-card-title>
<v-card-text>
...
The problem I have is that when I click the dropdown menu item, the dialog appears and works fine. Once I dismiss the dialog, I'm back to the page but the menu item (the "Agent List" dropdown itself) is still showing hovering above the rest of the page. How do I get the dropdown list to disappear after I select something from it?
the problem is if the list item is the activator then it must be open until the dialog is open
my solution would be:
<v-menu offset-y v-model="menu">
<template v-slot:activator="{ on, attrs }">
<v-btn v-bind="attrs" v-on="on">
<span><v-icon>mdi-menu</v-icon></span>
</v-btn>
</template>
<v-list>
<AdminAgentList #close-menu="menu = false" />
</v-list>
</v-menu>
adding a v-model to the menu and controlling visibility
and in the other component AdminAgentList:
watch: {
agentList_dlgOpen(val) {
if (!val) {
this.$emit("close-menu");
}
},
},
a watcher to check if the dialog closed
Try this.
<v-toolbar class="transparent">
<v-menu #input="onMenuToggle" open-on-hover v-model="isOpened" offset-y>
<template v-slot:activator="{ on, attrs }">
<v-btn v-bind="attrs" v-on="on">
<span><v-icon>mdi-menu</v-icon></span>
</v-btn>
</template>
<v-list>
<AdminAgentList/>
</v-list>
</v-menu>
export default {
data() {
return {
isOpened: false,
selectedCategori: [],
categori: {},
overlay: false,
};
},
methods: {
onMenuToggle(val) {
this.isOpened = val;
},
},
};
</script>
I'am using vuetify and i want make auto complete like the one on their official site.
But i'm faces some issues :
The items value not appear in the return list and i don't know how to make appear the links.
Here is my code.
Thanks You
<template>
<v-app>
<v-app-bar app color="primary" dark>
<v-app-bar-nav-icon #click="drawer = true"></v-app-bar-nav-icon>
<v-toolbar-title> Board </v-toolbar-title>
<v-spacer></v-spacer>
<v-autocomplete
:loading="loading"
:filter="v => v"
:items="items"
:search-input.sync="search"
v-model="select"
flat hide-no-data hide-details return-object placeholder="Search ...">
<v-list-tile
slot="prepend-item"
class="grey--text">
{{ items.length }} menus found
</v-list-tile>
<template slot="selection" slot-scope="{ item }">
{{item.name}} {{item.url}}
</template>
<template slot="item" slot-scope="{ item }">
<v-list-tile-content>
<p class='fullName'>{{item.name}} {{item.url}}</p>
</v-list-tile-content>
</template>
</v-autocomplete>
</v-app-bar>
<v-main>
<HelloWorld/>
</v-main>
</v-app>
I went through your issue and try to make a codepen and it worked.
My suggestion is that you should consider data structure when you use object with auto complete and it 's needed even you use v-select.
Please check this pen. https://codepen.io/endmaster0809/pen/qBZRywZ
items: [
{
name: 'Alerts',
url: 'https://vuetifyjs.com/en/components/alerts/'
},
{
name: 'Autocompletes',
url: 'https://vuetifyjs.com/en/components/autocompletes/#autocompletes'
}
],
select: {
name: 'Alerts',
url: 'https://vuetifyjs.com/en/components/alerts/'
},
How to use v-tooltip inside v-menu activator with vuetify 2.0? Previously it was working using slot="activator".
That's what I'm trying to combine:
<v-menu>
<template v-slot:activator="{on}">
<v-btn v-on="on">Menu Trigger</v-btn>
</template>
...list with menu options...
</v-menu>
and
<v-tooltip v-slot:activator="{on}">
<v-btn v-on="on">Menu Trigger with Tooltip</v-btn>
<span>Tooltip Content</span>
</v-tooltip>
Now I try to paste v-tooltip inside v-menu, what should happen with {on} here?
I think you're most likely unsure about the "conflicted" on objects passed to the template by multiple activator slots and how to apply all of the event handlers on the target element(s).
If that's the case, you can workaround this by assigning either one (or both) of them to a variable with a different name (see: assigning to new variable names), and then destructure and "restructure", which basically glues them back together (or merge them, technically speaking).
<v-menu>
<template #activator="{ on: onMenu }">
<v-btn v-on="onMenu">Menu Trigger</v-btn>
<v-tooltip bottom>
<template #activator="{ on: onTooltip }">
<v-btn v-on="{ ...onMenu, ...onTooltip }">Menu Trigger with Tooltip</v-btn>
</template>
<span>Tooltip Content</span>
</v-tooltip>
</template>
<!-- ...list with menu options... -->
</v-menu>
Or, use the slot props directly. Just make sure to name them properly so they won't introduce another naming conflict with the component's data and/or props.
<v-menu>
<template #activator="menu">
<v-btn v-on="menu.on">Menu Trigger</v-btn>
<v-tooltip bottom>
<template #activator="tooltip">
<v-btn v-on="{ ...menu.on, ...tooltip.on }">Menu Trigger with Tooltip</v-btn>
</template>
<span>Tooltip Content</span>
</v-tooltip>
</template>
<!-- ...list with menu options... -->
</v-menu>
Complete Demo:
new Vue({
el: '#app',
data: () => ({
items: [
{ title: 'Item #1' },
{ title: 'Item #2' },
{ title: 'Item #3' }
]
})
})
<link href="https://fonts.googleapis.com/css?family=Roboto:400|Material+Icons" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#1.x/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#1.x/dist/vuetify.js"></script>
<div id="app">
<v-menu>
<template #activator="{ on: onMenu }">
<v-btn v-on="onMenu">Menu Trigger</v-btn>
<v-tooltip bottom>
<template #activator="{ on: onTooltip }">
<v-btn v-on="{ ...onMenu, ...onTooltip }">Menu Trigger with Tooltip</v-btn>
</template>
<span>Tooltip Content</span>
</v-tooltip>
</template>
<v-list>
<v-list-tile
v-for="(item, index) in items" :key="index"
#click.prevent>
<v-list-tile-title>{{ item.title }}</v-list-tile-title>
</v-list-tile>
</v-list>
</v-menu>
</div>
I'm using a Vue.js project setup with Nuxt and Vuetify.js.
I'm trying to add FontAwesome icons as v-btns to lead the user to an Instagram page.
Unfortunately when clicking the icon, the browser is directed to http://localhost:3000/https://www.instagram.com/therock/?hl=en instead of just https://www.instagram.com/therock/?hl=en as expected. The Instagram account URL is tacked onto the end of the base URL.
Here's the template portion of the Vue file:
<template>
<v-app>
<v-toolbar app flat color="rgb(249, 249, 249)">
<router-link to="/" class="toolbar-title">
<v-toolbar-title>Chumiest Bucket</v-toolbar-title>
</router-link>
<v-spacer></v-spacer>
<v-toolbar-items class="hidden-sm-and-down">
<v-btn
v-for="(item, index) in items"
:key="index"
:to="item.path"
flat
>{{ item.name }}</v-btn>
<v-btn flat :to="instagram.path">
<font-awesome-icon :icon="instagram.icon"/>
</v-btn>
</v-toolbar-items>
<v-menu class="hidden-md-and-up">
<v-toolbar-side-icon slot="activator"></v-toolbar-side-icon>
<v-list>
<v-list-item v-for="(item, index) in items" :key="index">
<v-btn :to="item.path" flat>{{ item.name }}</v-btn>
</v-list-item>
<v-btn flat :to="instagram.path">
<font-awesome-icon :icon="instagram.icon"/>
</v-btn>
</v-list>
</v-menu>
</v-toolbar>
<v-content style="padding-top: 19px;">
<v-container>
<nuxt />
</v-container>
</v-content>
<v-footer app style="position: absolute;">
<span style="font-size: 8pt;">© 2019 Chumiest Bucket</span>
</v-footer>
</v-app>
</template>
here's the script portion of the Vue file:
<script>
export default {
name: 'app',
data() {
return {
fixed: false,
items: [
{
name: 'About',
path: '/about'
},
{
name: 'Stuff',
path: '/stuff'
}
],
instagram: {
icon: ['fab', 'instagram'],
path: 'https://www.instagram.com/therock/?hl=en'
},
}
}
}
</script>
The "to" prop is used for navigating to pages within your routes. See documentation here. To navigate to external links, Bind the url to href instead.
<a :href="instagram.path">
{{ url }}
</a>