Blog

Add Keyboard Shortcuts to your Vue App ⌨️

09.01.2020 | Tutorial Frontend | James McMahon

hero

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>{{ message }}</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.

Share

Read More

Related Posts

related_image

06.30.2021 | Culture | Katy Scott

At Focused Labs, collaboration is key to how we work together; it helps our teams learn from each other, brings us closer and helps us become more efficient...

related_image

06.23.2021 | Culture | Austyn

Late-night feedings and diaper changes, the 3-4 month sleep regression, teething, and a growth spurt all mean I'm getting less sleep than...

related_image

05.12.2021 | Culture Backend Frontend | Ryan Taylor

Temporarily disrupts "normal" business operations and allow self-organized teams to rapid prototype around their interest areas

related_image

04.27.2021 | Culture | Erin Hochstatter

Several years ago, I'd been trying to find an approach to software consulting that made sense for me [...]

related_image

01.28.2021 | Backend | Parker Drake

Recently I found myself needing to validate fields in a Spring Boot controller written in Kotlin...

related_image

01.22.2021 | Tutorial | Luke Mueller

⌘+⇧+g is the way to go

related_image

01.21.2021 | Devops | Katy G

Kube jobs running wild? To delete successful jobs...

additional accent
accent
FocusedLabs

171 N Aberdeen St
Suite 400
Chicago, IL 60607
(708) 303-8088

[email protected]

© 2021 FocusedLabs, All Rights Reserved.

  • facebook icon
  • twitter icon
  • linkedin icon
  • github icon