Alex
Alex

Reputation: 68072

Pass keyboard events to child component

See this simple modal component:

Vue.component('modal-content', {
  template: `
      <div class="modal">
         ...
      </div>
  `,

  props: ['title'],

});

How can I control keyboard press from the components that use it (parents)?

If I use @keyup.esc event then it does not have any effect:

<portal to="modal-wrap">
  <modal-content @keyup.esc="doSomething">
  </modal-content>
</portal> 

If I put @keyup.esc in the modal-content component on the DIV then it works, but that's no use to me because I need to call the doSomething function which exists in the parent component

Upvotes: 1

Views: 1974

Answers (3)

Lawrence Cherone
Lawrence Cherone

Reputation: 46650

Use refs (Accessing Child Component Instances & Child Elements)

<modal-content @keyup.esc="doSomething" ref="modal">

then inside the doSomething method:

this.$refs.modal.close();

presuming you have a close() method in the modal-content component.


You could also pass a prop, like you are doing with title:

<modal-content @keyup.esc="modalIsOpen = false" :modalIsOpen="modalIsOpen">

Vue.component('modal-content', {
  template: `
      <div class="modal" :class="{show: modalIsOpen}">
         ...
      </div>
  `,
  props: ['title' 'modalIsOpen'],
  //...
});

Upvotes: 1

MarcRo
MarcRo

Reputation: 2473

The reason your code is not working is because your you are trying to listen to a native browser event - which is not emitted by Vue, but by the DOM itself.

To react to these type of events you have to attach your listener to an actual HTMLElement - not a vue component. Since this is a common issue, vue provides a simple modifier that automatically attaches the eventlistener to the underlying HTMLElement: the .native modifier.

Try it like this

<portal to="modal-wrap">
  <modal-content @keyup.esc.native="doSomething">
  </modal-content>
</portal> 

You can find further information in vues documentation

Upvotes: 6

Loki
Loki

Reputation: 1205

You could do something like this in your doSomething function:

onClickButton (event) {
      this.$emit('clicked', 'someValue')
}

And in you parent component do this:

<template>
   <parent-component @clicked="handleClick"></parent-component>
</template>

For more info check this:

https://v2.vuejs.org/v2/guide/components.html#Listening-to-Child-Components-Events

And this:

https://medium.com/js-dojo/component-communication-in-vue-js-ca8b591d7efa

Upvotes: 3

Related Questions