I have a <Parent> component that renders the <Modal> component if a variable showModal is true.
The variable showModal is defined in the setup(){} function of the <Parent> component.
I want to close the modal when a user:
- clicks the close button
- when they hit the ESC button
Parent component
<template>
<Modal v-if="isShownModal" @clickedModalClose="isShownModal=false" @keydown.esc="isShownModal=false">
//removed some code for clarity purposes
</template>
<script>
export default {
components: {Modal},
setup(){
const isShownModal = ref(false)
...
Notice the @clickedModalClose="isShownModal=false" and @keydown.esc="isShownModal=false"
Modal component
<template>
<div class="modal is-active">
<div class="modal-background"></div>
<div class="modal-content box">
<slot name="header"></slot>
<slot name="body"></slot>
</div>
<!-- Listen to a custom event @clicked-modal-close (v-on) -->
<button @click="$emit('clickedModalClose')" class="modal-close is-large" aria-label="close"></button>
</div>
</template>
To close the modal I'm emitting an event when a close button is clicked within the child component and listening for that event @clickedModalClose and as expected that closes the modal correctly
Nonetheless, when I hit the ESC button nothing happens even though I have the event handler declared on the Modal component: <Modal v-if="isShownModal" @clickedModalClose="isShownModal=false" @keydown.esc="isShownModal=false">
I also tried attaching the @keydown.esc="closeTheModal()" to a DIV and template tag within the <Modal> and thenemitted the clickedModalClose event programatically within the closeTheModal() function , but to no avail
Could someone, please, shed some light to this problem :/
UPDATE
The correct answer is given by @blackgreen
After the component is rendered in order to handle the ESC event that event has to be attached to a DOM element within the component.
What I did is I simply used template references on the Modal closing button to have it available in the onMounted(){} hook and called the focus() method on it
Parent component
<Modal @keydown.esc="isShownModal=false">
Child component
<template>
<button ref="closingButton" class="modal-close is-large" aria-label="close"></button>
</template>
and in the JS part:
<script>
import {ref, onMounted} from 'vue';
export default {
setup(props, context){
const closingButton = ref(null)
onMounted(()=>{
closingButton.value.focus()
})
return {closingButton}
}
}