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
)
}
Related
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')
}
});
},
I'm using Element UI radio button group and I want to use preventDefault() when trigering change event:
<el-radio-group #change="changeHandler" v-model="radio1">
<el-radio-button label="New York"></el-radio-button>
<el-radio-button label="Washington"></el-radio-button>
<el-radio-button label="Los Angeles"></el-radio-button>
<el-radio-button label="Chicago"></el-radio-button>
</el-radio-group>
Script:
methods: {
changeHandler(value, e) {
// e is undefined
// here should be preventDefault
}
}
I tried set second parameter to change function, but it is undefined.
Element UI works a bit differently. #change just returns the value chosen, nothing else. We need to use native to access the Event object. But #change.native won't work, as the change has already happened (if you want to actually prevent the change). As a side note, I would use disabled attribute instead (like presented in documentation). In my opinion for the UX it's weird that a user cannot choose a radio button, but putting that aside.... Use #click.native instead if you want to prevent a choice:
#click.native="changeHandler"
Then you have access to the Event object:
changeHandler(e) {
console.log(e.target.value)
if(e.target.value == "Washington") {
e.preventDefault();
}
}
CODEPEN
You're having the parameters in the method wrong. The are 2 ways this can go using the #change event handler:
A
defining a change handler without arguments, like
<el-radio-group #change="changeHandler" v-model="radio1" ></el-radio-group>
changeHandler(e) {
// e will be the Event object
console.log(e)
}
B
defining a change handler with arguments, put in $event to still include the event object
<el-radio-group #change="changeHandler($event, 'string')" v-model="radio1" ></el-radio-group>
changeHandler(e, value) {
// e will be the Event object
console.log(e);
// value will be 'string'
console.log(value);
}
I have a v-data-table and the user can click on any row and a dialog opens. Inside on my vuetify dialog is a dropdown of data.
I want to filter this data everytime the user clicks on a row and filter out what the user clicked from the dropdown inside the dialog.
Here is my dialog:
<v-dialog v-model="edit" max-width="1200" #input="closeDialog()">
<editCompany :isEdit="true"
v-if="showEdit"
:company="selected"
:adminEdit="true"></editCompany>
</v-dialog>
You can see I'm passing in the values from the table row the user clicked.
Now, I need to use the value being passed in to filter the dropdown. The mounted event only runs once, so my logic inside of it only fires for the first row clicked.
Here is the mounted event inside of my editCompany template:
mounted: async function () {
this.filterOutResults(); //this is where i do my filtering and it works
},
Every other row the user clicks doesn't fire mounted, so I cant use that unless I can unmount the dialog when its closed.
I found how to fire an event when the dialog closes, but I cannot find a vuetify open event.
How do I run a function everytime the dialog opens so I can filter the results or how do I unmount the dialog everytime it closes, so the mounted event can run everytime? Thanks
For future references, I'll expand #mynd comment, which should be the answer:
export default {
data() {
return {
dialogVisible: false,
},
},
watch: {
dialogVisible(visible) {
if (visible) {
// Here you would put something to happen when dialog opens up
console.log("Dialog was opened!")
} else {
console.log("Dialog was closed!")
}
}
},
<v-dialog v-model="dialogVisible" max-width="1200" #input="closeDialog()">
<!-- Add code here, according to Vuetify docs -->
</v-dialog>
For further information (about constructing the v-dialog component itself), refer to the official docs
if you want to do something inside the dialog component when it's open, there is a little workaround that you can do.
<v-dialog v-model="edit" max-width="1200" #input="closeDialog()">
<editCompany :isEdit="true"
v-if="showEdit"
:company="selected"
:dialogOpen="edit"
:adminEdit="true"></editCompany>
</v-dialog>
as you see you can pass dialog's handler variable as dialog's parameter. its 'dialogOpen' in this case.
then inside editCompany component,
watch: {
'dialogOpen' :{
handler(newVal, oldVal) {
//do your stuff.
},
deep: true
},
}
So in short it will watch the variable which is controlling dialog, based on its value which mostly is true or false, you can do your operation.
My application dialog should respond to "Ctrl+S" for a save function and cancel the default browser Save event.
<div
#keyup.83="doSave"
#keyup.ctrl.83="doSave"
#keyup.alt.83="doSave"
tabindex="0">
The doSave event is fired on pressing 's' (and alt+s) but not on ctrl+s.
Why is ctrl+s not fired?
BONUS QUESTION: Is there a way to preventDefault without coding it? Somehow it should be possible adding .once but the docs are vague.
https://codepen.io/cawoodm/pen/qvgxPL
There are several questions packed into your question, so I am going to answer them one by one:
Why is ctrl+s not fired?
Several reasons. You are using the keyup event, while the browser starts to save the page on a keydown event. Your keyup event is thus never fired.
For any event to be registered on your div, your div must have focus, because otherwise the event will not originate from that element, but instead from (presumably) the body.
Is there a way to preventDefault without coding it?
Yes. Add the prevent modifier to your event. In the same way, you can use once to unregister an event after it has triggered once, stop to use stopPropagation() and passive to explicitly not stop propagation. You would use something like: #keydown.ctrl.83.prevent="saveMe".
How do I get this working?
If you are fine with the user having to focus the element before being able to save, and otherwise getting the default behaviour, use the following:
<div
id="app"
tabindex="0"
#keydown.ctrl.83.prevent.stop="saveInsideComponent"
>
<!-- -->
</div>
Otherwise, this is one of the few moments where registering your own event listener is useful. Just make sure to remove it before your component is destroyed, or you will have a rogue event listener throwing errors on other components + a memory leak to deal with.
mounted() {
document.addEventListener("keydown", this.doSave);
},
beforeDestroy() {
document.removeEventListener("keydown", this.doSave);
},
methods: {
doSave(e) {
if (!(e.keyCode === 83 && e.ctrlKey)) {
return;
}
e.preventDefault();
console.log("saving from DOM!");
},
}
#Sumurai8's answer is great but I would add support for apple devices by checking if e.metaKey is == true. The code then looks like this:
mounted() {
document.addEventListener("keydown", this.doSave);
},
beforeDestroy() {
document.removeEventListener("keydown", this.doSave);
},
methods: {
doSave(e) {
if (!(e.keyCode === 83 && (e.ctrlKey || e.metaKey))) {
return;
}
e.preventDefault();
console.log("saving from DOM!");
},
}
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