SnazzyPencil
SnazzyPencil

Reputation: 79

@keydown.ctrl and @keyup.ctrl event modifiers not responding to respective keyboard events vujs

I'm writing a VueJS application that will have a custom context menu that appears when the user mouses over a particular item on the page. The menu is dynamic meaning that it will change as the user hovers over different items. If the user holds down the control key the menu will be static so that they can interact with the items in the menu.

My issue is the while the @keydown.ctrl="..." event seems to respond as intended the @keyup.ctrl="..." event does not. I have looked around and tried different modifiers such as .exact and .caputure but they don't seem to solve the issue.

What does work however is changing @keyup.ctrl to @keyup.control. The .control works on the @keyup event but not for the @keydown event.

What is the difference between @keydown and @keyup that would require the use of different key modifiers?

Below is an example of what the root element looks like.

<div
  tabindex="0"
  @keydown.esc.exact="() => (displayContext = false)"
  @keydown.ctrl.exact="() => (keepContext = true)"
  @keyup.control="() => (keepContext  = false)"
>
...
</div>

Upvotes: 2

Views: 1942

Answers (2)

kissu
kissu

Reputation: 46594

You can use this website to visually which keys are triggering which event: https://config.qmk.fm/#/test
or even on this one: http://keycode.info/

As you can see, you cannot have a listener on the ctrl key alone. You either need a ctrl + a or another key paired with it to effectively track it.

Here is the best implementation that we can have to track the ctrl event without any other key pressed:

  • hold ctrl and hover the div (@mouseover.ctrl="holdCtrlAndHover")
  • while holding ctrl, leave the div (@mouseleave.ctrl="holdCtrlAndLeave")
  • hold ctrl, hover on the div, then mouse click (@click.ctrl="hoverAndHoldCtrlThenMouseClick")

Example of the implementation: https://codesandbox.io/s/lingering-violet-q5gct?file=/src/App.vue


For a quick reference on MouseEvent.ctrlKey, here it is: https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/ctrlKey

Here is a quick explanation of the differences on the event key listeners: onKeyPress Vs. onKeyUp and onKeyDown
Good to know: keypress event is now deprecated

Upvotes: 2

Joshua Angnoe
Joshua Angnoe

Reputation: 1075

There may be a couple of problems related to this.

Capturing keydown events (from vue template) is most reliable when you are trying to capture keydowns of an input (input, select or textarea) element. Because when you focus on the element all keyboard events are triggered on the this element. In your example you have a few divs on the page and these may not be the active element. A suitable workaround for this would be to capture all keydown or key keyup events on the document.body and checking if the event.target matches your criteria. Another benefit is you can keep your template code simpler (especially when you have many contextmenu areas.)

mounted() {
   this.keepContext = false;

   document.body.addEventListener('keydown', event => {
      if (event.key == 'Control') { 
         this.keepContext = true;
      }
   });
   document.body.addEventListener('keyup', event => {
      if (event.key == 'Control') { 
         this.keepContext = false;
      } else if (event.key == 'Escape') { 
         // hide the contextmenu
      }
   });
}

Another subject that you raised, the difference between @keydown.ctrl and @keydown.control.

The first: the .ctrl event modifier is usually used in combination with another key, (example: '@keydown.ctrl.s="autoSave"')
The second: .control is fired when you press the key control and cannot be used in combination with another key.

I have experimented with these two setups:

<input
    @keydown.control="logKeydown"
    @keyup.control="logKeyup">
>

and this

<input
    @keydown.ctrl="logKeydown"
    @keyup.ctrl="logKeyup">
>

And the setup with @keydown.control does works reliably. The @keyup.ctrl does not work reliably (sometimes it misses the keydown, sometimes it misses the keyup).

All in all I'd recommend listening to keyboard events on the document.body when using non-input elements. Second best is using the .control modifier (instead of the .ctrl) modifier.

Upvotes: 1

Related Questions