How can i close a vuetify's dialog opened without an activator, when the user press the ESC key on the keyboard?
Add #keydown.esc="dialog = false" to v-dialog component
<v-dialog v-model="dialog" #keydown.esc="dialog = false"></v-dialog>
data: () => ({
dialog: false
}),
Working example:
https://codepen.io/anon/pen/BJOOOQ
Additionally, if using dialog as custom component then possibly we need to emit input event:
<template>
<v-dialog :value="value" #keydown.esc="$emit('input')">
...
This is the only way I was able to get it to work
mounted() {
// Close modal with 'esc' key
document.addEventListener("keydown", (e) => {
if (e.keyCode == 27) {
this.$emit('close');
}
});
},
this code maybe can help you
mounted() {
let self = this;
window.addEventListener('keyup', function(event) {
// If ESC key was pressed...
if (event.keyCode === 27) {
// try close your dialog
self.advanced_search = false;
}
});
},
the same principle as adding keypress binding to any vue component should work - add the following code to the v-dialog component :
#keydown.esc="dialog = false"
working example ( note the close button click event handler as well )
https://codepen.io/yordangeorgiev/pen/WBeMGq
While the solutions others have mentioned work, there still are conflicts with the bounce animation, making it not work after playing it by clicking outside the dialog, etc.
Setting the no-click-animation property also fixes the animation when closing as otherwise it plays both the close and bounce animation:
<v-dialog v-model="dialog" #keydown.esc="dialog=false" no-click-animation></v-dialog>
#keydown.esc not working with my project. As far as I see it's good for Vue2 projects.
Working script:
mounted() {
document.addEventListener("keydown", (e) => {
if (e.key === 'Escape') {
this.$emit('close');
// Or any other way you want to close your modal
}
})
}
What you want to use is a Key Modifier. You can use v-on:keyup.esc directive on your dialog to detect if the escape key is detected.
Read this for more information about Key Modifiers
Related
I recently had to add event handler to vuetify dialog's overlay and it works.
Opening / closing dialog is controlled by a boolean variable dialog:
<v-dialog v-model="dialog">
<MyComponent v-if="dialog" />
</v-dialog>
And some codes to add / remove handler:
openDialog() {
this.dialog = true
setTimeout(() => {
const overlay = document.querySelector('.v-overlay--active .v-overlay__scrim')
if (overlay) {
overlay.addEventListener('my-event', this.myEventHandler)
}
}, 100)
},
closeDialog() {
const overlay = document.querySelector('.v-overlay--active .v-overlay__scrim')
if (overlay) {
overlay.removeEventListener('my-event', this.myEventHandler)
}
this.dialog = false
},
My concern is that, as closeDialog is not always called (e.g. when clicking outside of the dialog), do I need to worry about memory leaks in this case?
The dialog overlay seems like getting inserted / deleted by vuetify library and I'm not sure if these changes will make trouble or not.
My question was quite vuetify specific. I didn't know the existence of event click:outside available for v-dialog. Also I had to make the dialog persistent and handle keyup event for esc to dismiss the dialog:
// #keyup.esc="handleEsc" somewhere close to top
<v-dialog v-model="dialog" persistent #click:outside="closeDialog">
<MyComponent v-if="dialog" />
</v-dialog>
So now I'm explicitly handling all events to dismiss the dialog and confident that no need to worrying about memory leaks.
It seems that the Vue #keydown on v-dialog/v-overlay stops working when a < v-card > is present. Why does this not work, and how to fix?
<v-overlay :value="olyThing" #keydown.esc="olyThing=false" tabindex="0">
<v-card
width="80vw"
height="80vh"
#click="olyThing=false">
</v-card>
</v-overlay>
While this does does work:
<v-overlay :value="olyThing" #keydown.esc="olyThing=false" tabindex="0">
</v-overlay>
Somehow the v-card is preventing the keydown to come through. Tried to put the #keydown on the v-card, but this doesn't fix it. Same effect on a v-dialog, instead on a v-overlay. I also tried doing a #keydown.native.esc, but nothing seems to work.
I'm not looking for a solution involving an eventHandler on the window. I'd like to keep this localized to the component.
I have not been able to figure out why the v-card prevents the #keydown to function. But an alternate solution that still is only active on the current page and not global is this:
A complete setup requires three parts.
The method to call when a key is pressed.
Adding the event listener.
Removing the event listener.
You will need the separate method in order to destroy the event listener later:
methods: {
onKeydown(e) {
if (this.isOverlay) {
if (e.keyCode == 37) {
console.log('LEFT')
} else if (e.keyCode == 39) {
console.log('RIGHT')
}
}
},
}
mounted() {
// Keypresses on overlay:
document.addEventListener('keydown', this.onKeydown)
},
beforeDestroy() {
document.removeEventListener('keydown',this.onKeydown)
},
Thanks to Watermelon Sugar for the suggestion.
Try this approach:
mounted() {
document.addEventListener("keydown", (e) => {
// If ESC key was pressed
if (e.keyCode == 27) {
this.showdialog=false
// or if you have created a dialog as a custom component, emit an event
// this.$emit('closeDialog')
}
});
},
In VueJS, I'm using v-tooltip (https://github.com/Akryum/v-tooltip) for popovers.
In order to close a popup, they provide a directive called 'v-close-popover' which I can assign to a button/link inside the popover to close the popup. This works well.
However, I have a requirement where I need to close this popup from a Vue method. But I dn't know how to trigger closing of the popover from the method.
This is how you can achieve this.It will display tooltip on mouseOver event and remove on mouseLeave event.
In template->
<i
id="requiredIcon"
aria-hidden="true"
v-tooltip="{content: 'Required option is not available for this question.', show: isOpen, trigger: 'manual'}"
#mouseover="showTooltip"
#mouseleave="removeTooltip"
></i>
In Script->
data() {
return {
isOpen: false,
};
},
methods:{
showTooltip() {
this.isOpen = true;
},
removeTooltip() {
this.isOpen = false;
}
}
In case anybody else stumbles upon this issue, the v-popover component has a hide method. So if you were to place a ref on your popover component then you can access the hide method from it and call it :)
I'm trying to focus a text field on ALT + C shortcut (in my Electron-Vue app):
Codepen: https://codepen.io/anon/pen/aqrBzq?editors=1010
The codepen uses this v-text-field custom component and as this comment on Github says, the method should be wrapped with $nextTick in order to focus this component
Need this, but doesn't work
<v-text-field
ref="filter"
#keyup.alt.67="focusFilter"
label="type here" >
</v-text-field>
...
methods: {
focusFilter(event){
this.$nextTick(event.target.focus)
}
}
This works, but is not what I need:
I also tried this code below, trying to focus it with a button, and it works, but I want to make it work with a key shortcut (for example ALT + C but more preferably CTRL + F, but for the sake of example I don't use reserved shortcut)
<v-btn #click="focusFilter()">focus</v-btn>
...
methods: {
focusFilter(event){
this.$nextTick(this.$refs.filter.focus)
}
}
When you're listening for a native event on a component you need to use the .native modifier.
So use this instead:
#keyup.native.alt.67="focusFilter"
Details here: https://v2.vuejs.org/v2/guide/components.html#Binding-Native-Events-to-Components
If you want to focus this input when alt+c is pressed and anything is focused you'd need to add an event handler to window for keyup.
I'd created a method to focus it under the right circumstances like:
methods: {
listenForFocusFilterShortcut (event) {
if (event.keyCode === 67 && event.altKey) {
this.$refs.filter.focus()
}
},
}
Then, add a created hook and attach this callback to the window when there's a keyup event.
created () {
window.addEventListener(
'keyup',
this.listenForFocusFilterShortcut
)
},
Then, remove the event listener when the component is removed:
destroyed () {
window.removeEventListener(
'keyup',
this.listenForFocusFilterShortcut
)
}
I have added navigation to the drawer, everything works fine except the case when the link is the same as the page is. The drawer left open after clicking on the link and it isn't obvious for the visitor that the page is the current page.
I have tried to do something like this #click.stop="(this.router.path != '/' ?
this.router.push('/') : drawer = !drawer)" Vue doesn't rapport any mistake and the code doesn't work.
Where am I wrong?
The drawer data key is looking for a boolean, if it's truthy the navigation drawer will show. So, you can add #click="drawer = false" to your menu links, and it will close the draw when any link is clicked.
Example in the docs: https://vuetifyjs.com/components/navigation-drawers#example-6
I handled this by making the drawer in my app a child of the route that uses it. The isOpen property is managed in the parent. I pass isOpen as a prop to the drawer and emit open and close events as appropriate.
Oh, I also found that timeouts are necessary to ensure the open / close animations work correctly. Someone please let me know if you found a better way to handle animations as this feels a little wonky.
I handle a few other things, like right/left justify and a return route, but ignore the noise if it isn't helpful.
Here's a parent loading the component
<my-drawer
:iconName="'my_icon'"
:isOpen="drawerIsOpen"
:justify="'right'"
:returnRoute="'home'"
#close="drawerIsOpen = false"
#open="drawerIsOpen = true"
>
// ...
</my-drawer>
Here are the methods from within the drawer component:
data() {
return {
closeDelay: 500,
width: 0,
};
},
methods: {
closeBtnClick() {
this.$emit('close');
setTimeout(() => { this.$router.push(this.returnRoute); }, this.closeDelay);
},
mounted() {
setTimeout(() => { this.$emit('open'); }, this.closeDelay);
},