Add Keyboard Shortcuts to Your Vue App ⌨️
Vue has built-in support for key events on input elements, but global shortcuts require a different approach. This post walks through how to implement global keyboard shortcuts in Vue using either low-level JavaScript event listeners or the vue-shortkey plugin.
Sep 1, 2020

I recently had to add some support for global key shortcuts in a Vue application I am working on. Vue has built-in support for listening to keys when you are in an input element. What is not supported directly are global shortcuts. For instance, if I am viewing an email in Gmail, I can hit 'a' to answer that email.
To accomplish this in Vue with either need to use low-level JavaScript event listeners or a plugin, like vue-shortkey. The approaches are not actually that different since vue-shortkey is, not surprisingly, just wrapping event listeners. It is straight forward to write your own event listener in a component so I didn't see a huge amount of value in using a plugin. There are a few blog posts covering event listeners in Vue already, but I am going to take a stab a showing a more complete example here, including how to test the component.
Implementing
Let's say we wanted to create a component that displays a message whenever the escape key is pressed.
Our Template block:
<div>{% raw %}{{ message }}{% endraw %}</div>Our Script block (Typescript):
import Vue from "vue";
export default Vue.component("Demo", {
created() {
window.addEventListener("keydown", this.escapeListener);
},
// make sure you remove the listener when the component is no longer visible
destroyed() {
window.removeEventListener("keydown", this.escapeListener);
},
data: function() {
return {
message: ""
};
},
methods: {
escapeListener(event: KeyboardEvent) {
if (event.key === "Escape") {
this.message = "Escape has been pressed";
}
}
}
});If you prefer to use class syntax, change the script block to the following:
export default class Demo extends Vue {
private message = "";
private created() {
window.addEventListener("keydown", this.escapeListener);
}
private destroyed() {
window.removeEventListener("keydown", this.escapeListener);
}
private escapeListener(event: KeyboardEvent) {
if (event.key === "Escape") {
this.message = "Escape has been pressed";
}
}
}Testing
This is all well and good, but it was not immediately clear how you test this behavior. After a few false starts, I stumbled upon a Github issue thread with the solution.
The magic I was missing was to use the Vue testing utils attachToDocument option when mounting or shallow mounting the component under test. Once we attach our component to a document, we can use wrapper.trigger to simulate our keypresses.
describe("Demo.vue", function() {
it("Displays a message when escape is pressed", function() {
const wrapper = shallowMount(Demo, { attachToDocument: true });
// the browser will add 'key' to the event,
// but when testing we need to add it manually
wrapper.trigger("keydown.esc", { key: "Escape" });
expect(wrapper.text()).to.include("Escape has been pressed");
// always make sure to destroy when using attachToDocument
wrapper.destroy();
});
});And that is it, a straightforward way to test-drive our global shortcuts as we add them to our component.
We’ll use the information you provide to respond to your enquiry. Learn more about how we handle your personal data in our Privacy Policy.
