rawilk / vue-context Goto Github PK
View Code? Open in Web Editor NEWA simple vue context menu component.
Home Page: https://randallwilk.dev/docs/vue-context
License: MIT License
A simple vue context menu component.
Home Page: https://randallwilk.dev/docs/vue-context
License: MIT License
The menu is not aligned properly if the parent element is positioned using CSS transform. For example when using a modular layout system - https://jbaysolutions.github.io/vue-grid-layout/examples/01-basic.html
Getting a Syntax error (not a lot of information) in the line that contains this file.
vue-context/src/js/normalize-slot.js
Any idea why this might be happening?
We are using core-js as a polyfill for ES6
Thanks!
Hello,
how can I use component without npm.
where src can be downloaded?
Type definition
Any plan to have type definition? Let me know if I can help you with that by any chance.
6.0.0
Maybe It would be better if we have an OnClose event to handle menu closing?
close () {
this.top = null;
this.left = null;
this.data = null;
this.show = false;
this.$emit('close');
},
The window scrolls when context menu shows
50px
and a div that has an height of calc(100vh - 50px)
100%
inside that second div which activates the context menu on row clickExpected behavior:
Do not scroll
Actual behavior:
The window scrolls
Can be seen here:
https://gyazo.com/f78f5eaa2b03eeef4b8d0af2e52bb1f0
"vue-context": "^3.1.0",
As Vue 3 has RC It will be a good idea to add support for Vue 3.
I haven't tested it yet but we will surely do it within a month so I wanted to know will this package get Vue 3 support?
Hello! i faced a strange issue while testing my application. i've got wrapping component named as 'ContextMenu' which contains imported 'vue-context' and renders menu items in a loop. Everything works fine, but jest test fails because vue-context module is exported twice. Here is the error:
\node_modules\vue-context\src\js\index.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){export { default } from './vue-context';
SyntaxError: Unexpected token 'export'
Full description of the error - http://prntscr.com/tcirgu
As i understand the problem is in the module here
export { default } from './vue-context';
export { default as VueContext } from './vue-context';
If needed, the full code of the component:
<template>
<vue-context
ref="menu"
@close="clear"
class="c-context-menu position-fixed bg-white shadow-light rounded-sm border-0"
>
<div
v-for="(m, index) in filteredData"
:key="index"
@click.prevent="m.handler(item.id)"
class="c-context-menu__item position-relative pl-4 pr-4 pt-3 pb-3 cursor-pointer"
>
<i :class="`c-context-menu__item-icon mr-2 ${m.icon}`" />
{{ m.title }}
</div>
</vue-context>
</template>
<script>
import VueContext from 'vue-context'
export default {
name: 'ContextMenu',
components: { VueContext },
data() {
return {
item: {},
data: []
}
},
mounted() {
this.$bus.$on('contextMenuOpen', this.open)
},
computed: {
filteredData() {
if (Object.prototype.hasOwnProperty.call(this.item, 'deleted_at')) {
if (this.item.deleted_at === null) {
return this.data.filter(m => m.title !== 'Восстановить')
}
return this.data.filter(m => m.title !== 'В архив')
}
return this.data
}
},
methods: {
open(event, item, data) {
console.log(event, item, data)
this.data = data
this.item = { ...item }
this.$refs.menu.open(event)
},
close() {
this.$refs.menu.close()
this.clear()
},
clear() {
this.item = {}
this.data = []
}
},
beforeDestroy() {
this.$bus.$off('contextMenuOpen')
}
}
</script>
And the minimal jest test code to reproduce the issue:
import {
mount,
createLocalVue,
enableAutoDestroy
} from '@vue/test-utils'
import ContextMenu from '@/components/ContextMenu' // wrapping component for 'vue-context'
let wrapper
let testHandler
let spyOnMenuOpen
let spyOnMenuClear
const localVue = createLocalVue()
describe('ContextMenu', () => {
enableAutoDestroy(afterEach)
beforeEach(() => {
wrapper = mount(ContextMenu, {
mocks: {
$bus: {
$on: jest.fn(),
$off: jest.fn(),
$emit: jest.fn()
}
},
localVue
})
testHandler = jest.fn()
spyOnMenuOpen = jest.spyOn(wrapper.vm.$refs.menu, 'open')
spyOnMenuClear = jest.spyOn(wrapper.vm, 'clear')
wrapper.vm.open({}, { id: 1, name: 'test' }, [
{
icon: 'el-icon-edit',
title: 'test1',
handler: testHandler
},
{
icon: 'el-icon-s-cooperation',
title: 'test2',
handler: testHandler
}
])
})
it('Render menu items', (done) => {
wrapper.vm.$nextTick(() => {
expect(wrapper.find('.c-context-menu__item').length).toBe(2)
})
})
})
5.2.0
If you install vue-context
using npm
, it's not possible to style it.
The styling is baked in dist/index.js
, and the SASS
files are not included (due to .npmignore
)
I have this scenario: component A has vue-context component. B is children from A, and have several other components (children of B), how to open context menu properly from an children of B? It is possible?
Most context menus allow using the up and down arrows to change the selected context menu item as well as using the enter key to select the selected item.
It is possible to show menu by left click event?
Hello,
I can't get vue-context to work with buefy Table's. (buefy = bulma css framework for vue; https://github.com/buefy/buefy)
I get the following error:
[Vue warn]: Error in nextTick: "TypeError: Cannot read property 'clientY' of undefined"
<b-table :data="clients_filtered" :paginated="true" :per-page="perPage" :current-page.sync="currentPage" :pagination-simple="false" :pagination-position="'bottom'" :default-sort-direction="'asc'" @contextmenu="rightClickClient" sort-icon="caret-down" sort-icon-size="is-small" aria-current-label="Current page"> </b-table>
And the function:
rightClickClient: function(client, event) { event.preventDefault() this.$refs.menu.open() }
<vue-context ref="menu"> <li> <a href="#" @click.prevent="onClick($event.target.innerText)">Option 1</a> </li> <li> <a href="#" @click.prevent="onClick($event.target.innerText)">Option 2</a> </li> </vue-context>
Hi,
I'm using the context-menu in multiple equal components. The is a small issue:
When I open the context-menu on one component and then right-click on another component the previous menu stays open.
What I could do is that every time time a new menu is open an event is emitted to all other components and close the other menus, but this solution doesn't seems really practical.
Is there another way?
I know this is silly, but when the :lazy="true"
prop is set, is it possible for the animation to hide the menu to be smoother?
By the way, awesome plugin!
I'm using the popover in ElementUI, which uses popper.js. When I put a vue-context menu inside of the popper, it does not close if i click somewhere else in the popover.
https://codesandbox.io/s/vue-template-g80uj
Expected behavior:
The vue-context menu to close
Actual behavior:
It stays open
Reproduces how often:
100%
4.0.1
Hi,
Might be an edge case, but I thought I'll let you know.
If there are two menu components on the same page:
<VueContext ref="menu1"></VueContext>
<VueContext ref="menu2"></VueContext>
If you right click on an element to open menu1
, and then go and click on something else to open menu2
, the menu1
remains open. Expected (intuitive) behavior would be for old menu to close.
Also, with either or both menus open, if you right-click on an element that is not handled by vue-context
(you get default browser right-menu), the vue-context
menus remain open. Expected (intuitive) behavior would be for vue-context
menu(s) to close.
Thanks for making the component!
Obviously the main purpose of this package is to allow for a right click to open a contextmenu.
However it should in theory work for left clicks as well.
I thought this would be a simple case of replacing @contextmenu
with @click
.
However I found that clickaway is detecting the click and closing the context menu instantly.
Removing v-on-clickaway
allows for a left click context menu but obviously the context menu just stays open indefinitely.
I also tested the old branch that used @blur
and a left click was possible. So removing this ability may have been an unintentional side effect of using clickaway.
I haven't been able to figure out a way to fix this yet.
The nested menu doesn't render on Safari/MacOS.
Expected behavior: The nested menu is visible.
Actual behavior: Only the first (non-nested) menu is visible. The nested menu (the second one) is not visible, except a very tiny part of it, which seems to be the part of it that is overlapping with the first (non-nested) menu.
Seen in versions 5.2.0 and 6.0.0
Tested on:
I unfortunately don't have a Mac myself that could possibly run Safari, so I can't really test and debug it myself, but I've added a screenshot.
After upgrading from 4.1.0 to 5.0, VueContext doesn't work anymore.
The console shows the following error when loading the app:
vue-context.js?8c7c:206 Uncaught ReferenceError: Invalid left-hand side in assignment
The menu is closed if you left-click away, but not if you right-click away.
Using the latest version and menu appears just fine.
However, I am trying to adjust the menu height (I guess more importantly the menu items)
First, thank you for all your work on this lib, it is greatly appreciated 👍
Line 1 in 39adea9
Why not just export this as default instead of making it so that we have to use destructuring to import it?
Reason I ask is if we are doing code splitting it requires more code, when it could just be exported as default since there's nothing else being exported (so even tree shaking wouldn't matter in this situation)
#33 (comment)
This could be both a named export and default export (to maintain backwards compatibility)
My template
<div>
<button @click="open" @contextmenu.prevent="open">
<v-context ref="menu">
<ul>
<li>Delete</li>
</ul>
</v-context>
</div>
My method
open(event) {
this.$refs.menu.open(event)
}
Both left & right click are excute function "open", but only right click can show the context menu.
Please help me, thank you!
Currently if the menu is open and the page is scrolled, it follows you. The menu should really just disappear when the page is scrolled.
Excellent work.
In the open source EMR I am trying to integrate the vue-context.
Looking at the examples it seems I will loose the functionality of "cut" "copy" "paste"
Is that correct ?
v.3.3.1
I'm seeing a ton of "close" events being emitted on scroll, even when the context menu is closed. Is this normal behavior? Do I need to worry about the flurry of emitted events impacting performance or memory?
I know that this it won't be the right place, sorry... but, is the documentation site down? it keeps on giving error 500
Thanks!
Add a prop similar to CloseOnScroll that allows the customization of whether the context menu closes on click
<template>
<div class="v-context"
v-show="show"
:style="style"
tabindex="-1"
@blur="close"
@click="tryCloseOnClick"
@contextmenu.capture.prevent
>
<slot :data="data"></slot>
</div>
</template>
<script>
export default {
props: {
closeOnClick: {
type: Boolean,
default: true
},
closeOnScroll: {
type: Boolean,
default: true
}
},
computed: {
...
methods: {
/**
* Add scroll event listener to close context menu.
*/
addScrollEventListener () {
window.addEventListener('scroll', this.close);
},
/**
* Close the context menu.
*/
close () {
this.top = null;
this.left = null;
this.data = null;
this.show = false;
},
tryCloseOnClick () {
if (this.closeOnClick) {
this.close();
}
},
dist/js directory seems to be missing from 5.0.0
When I upgraded from a very early version to 5.0.0 I got the message
ERROR in ./node_modules/vue-context/dist/js/vue-context.js
Module build failed: Error: ENOENT: no such file or directory, open '/Users/......../node_modules/vue-context/dist/js/vue-context.js'
There is a src/js directory and when I copy that one into dist, the error message disappears but the menu appears before clicking on it
I also get the following warning:
[Vue warn]: Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option.
And obviously, when I right click :
[Vue warn]: Error in v-on handler: "TypeError: this.$refs.menu.open is not a function"
So it seems the vue-context is not properly recognized.
4.1.1 though has the proper structure
Hello!
I'm stuck on working with the vue-context. I don't know if it is a bug or if i wrote something false, if i open one contextmenu everything happens fine but if i start opening another one the first one opened should normally close automatically but in my case now both are opened.
Is it supposed to work like this? If yes, how can i achieve that only one is opened?
Thanks 👍
Context-Menu won't close if you click on an iframe after you opened the Context-Menu.
**Expected behavior: Close Context Menu
**Actual behavior: Context Menu stays open
**Reproduces how often: 100%
^5.0.0
Electron
i am using a Vue-Tree and its render in Script tag like this
tpl(...args) {
const { 0: node, 2: parent, 3: index } = args;
let titleClass = node.selected
? "node-title node-selected"
: "node-title";
if (node.searched) titleClass += " node-searched"; //search
return (
<span>
<span
class="tree-expand"
onClick={() => {
this.popupActive2 = true;
this.waitFor(_ => this.confirmClose === true).then(_ =>
this.AsyncaddNode(node)
);
}}
>
<b class="text-xl">+</b>
</span>
<span
class={titleClass}
domPropsInnerHTML={node.title}
onClick={() => {
HERE I WANT TO DO THE RIGHT CLICK FUNCTION
}}
></span>
</span
i want to use the right click Function
I tried to install it globally in main.js like this.
import { VueContext } from 'vue-context';
Vue.use(VueContext);
<vue-context ref="menu">
<li>
<a href="#" @click.prevent="onClick($event.target.innerText)">Option 1</a>
</li>
<li>
<a href="#" @click.prevent="onClick($event.target.innerText)">Option 2</a>
</li>
</vue-context>
Expected behavior: [What did you expect to happen]
The vue-context did not render correctly.
Actual behavior: [What actually happens]
The vue-context should render correctly.
Reproduces how often: [What percentage of the time does it reproduce?]
Always
^5.1.0
I'm having an issue where I want to dynamically update the item selector in the component under certain conditions (I have a submenu in my context menu, and when it's open, I only want the keyboard nav to cycle through the sub menu items, which have a different class)
As you can see in the cache, the itemSelector property gets updated by the parent component, but the internal localItemSelector data remains cached, and doesn't update.
This prevents the keyboard navigation from cycling through the elements I need under those conditions.
contextItemSelector() {
return this.subMenuOpen ? '.context-option--submenu' : '.context-option';
},
<vue-context ref="menu" :item-selector="contextItemSelector">
Expected behavior: I expect the class selector to update
Actual behavior: The component gets the initial state, but doesn't update.
Reproduces how often: 100% of the time
Package : 4.0.1
Browser: Chromium (Electron)
Using vue-context
increases bundle size by 41 KB (gzipped). It seems tree-shaking is not working properly, and the whole core-js
in bundled in, not just the two functions used.
Hello,
I'm unable to pass data from the contextmenu, taken from the advanced usage part in usage examples.
I don't get any errors, but console log returns undefined.
Expected behavior: [Debug console to return value 'foo'.]
Actual behavior: [Console returns undefined.]
I'm using vue-context as Nuxt plugin. Everything works great, but this one feature.
I'm also using template slot-scope="child" instead of template scope="child"
Note that I am using vue-context version 4.0.2.
This component will fail when used inside of a v-for loop. Per Vue's documentation on ref:
When used on elements/components with v-for, the registered reference will be an Array containing DOM nodes or component instances.
I have attempted to get around the issue by using a method openMenu
.
<ul>
<li v-for="item in items" :key="item.index">
<vs-button @contextmenu.prevent="openMenu(item.index)">{{item.label}}</vs-button>
<vue-context ref="menu" :data="item.index">
<ul>
<li @click="unpinItem(item.index)">Unpin</li>
</ul>
</vue-context>
</li>
</ul>
methods: {
openMenu(itemIndex) {
for (const [index, VueComponent] of this.$refs.menu.entries()) {
if (VueComponent.$attrs.data === itemIndex) {
this.$refs.menu[index].open();
break;
}
}
},
unpinItem(itemIndex) {
this.$store.dispatch('unpinItem', {
index: itemIndex,
});
},
}
However, I get a couple errors when I try and fire the open
event this.$refs.menu[index].open();
Error in nextTick: "TypeError: Cannot read property 'clientY' of undefined"
TypeError: Cannot read property 'clientY' of undefined
I was reading through your advanced documentation, but I see no mention of using this context menu inside of a v-for loop.
How do you recommend this be handled?
Hi, thanks for this useful component.
How can i change hover color?Is any prop to set?
When UI element is draggable - context menu can't be closed by click outside menu and shown in wrong place.
Expected behavior:
The context menu is hidden
Actual behavior:
The context menu is shown and placed in the wrong spot
Reproduces how often: [What percentage of the time does it reproduce?]
100%
5.0.0
Chrome 78.0.3904.108 64bit
Hello,
I just started using your plugin and I might need it in a lot of components. Is it possible to globally define your component?
I tried registering it with Vue.component, but weirdly it didnt't work.
Best wishes
First of all thanks for this package. It is by far the best context menu for vue! :)
But I miss the ability to create nested menus. I already tried to add another list on hover, but it still fires the click event of the parent element. And it feels hacky the way I did it.
Do you have any plans to add such a feature? If you need any help/testing I'd love to help. 😀
@close does not fire when the context menu is closed via selecting an item with the mouse or with the keyboard.
4.0.0
After upgrading from 4.0.3 to 4.1.0, VueContext doesn't work anymore.
The console shows the following error when loading the app:
vue.runtime.esm.js:619 [Vue warn]: Unknown custom element: <VueContext> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
And the menu doesn't show up, instead I get this error:
Uncaught TypeError: open is not a function
NOTE: ISSUES ARE NOT FOR CODE HELP - Ask for help at
https://stackoverflow.com
As per title, not working with Nuxt. It works fine unless you refresh the page. Once the page is refreshed it crash with error: "Window is not defined". I tried using it as suggested by you and also as suggested by Nuxt, including it in the plugins section. Nothing...
Expected behavior: The app should not crash on page refresh
Actual behavior: It crash on page refresh
Reproduces how often: Every time. 100%.
When I use the context menu in a project, the buttons seem to be wider than the context menu holding them:
image
In addition, when running in chrome, there is a blue outline to the menu.
Either clone https://github.com/guyguy2001/vue-context-reproduction and run it via npm i
, npm run serve
, or:
vue create vue-context-reproduction
(I used the default babel + eslint setup).App.vue
or HelloWorld.vue
, and modify them to fit inside the component (Make sure to remove the li
styling from the example component).npm install vue-context
, npm install
, npm run serve
.Expected behavior: [What did you expect to happen]
A normal context menu appearing, like in the example screenshots.
Actual behavior: [What actually happens]
The context menu appears, but has a blue outline (Only on chrome), and the buttons are wider than the context box, meaning that the text is centered weirdly, and when I hover over a button, its background is too wide.
Reproduces how often: [What percentage of the time does it reproduce?]
The problem occurs consistantly, whenever I run the project.
Version: 4.0.1 (doesn't happen on 3.4.0)
Chrome: Version 74.0.3729.169 (Official Build) (64-bit)
Firefox: 64.0 (64-bit)
I'm building little app in meteor+vue.js. As soon as I add
import { VueContext } from 'vue-context';
or
import VueContext from 'vue-context';
to component it start to crash with error message:
SyntaxError: export declarations may only appear at top level of a module
Any way to fix it?
I tried to use it from child components but not able to do so. Is there any way to call it from inside a method. Thanks in advance
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.