'Check if a component has an event listener attached to it
Assuming there's some <Form> component. It can be called with a @cancel event listener attached to it and if it's the case, I want to show the cancel button that triggers this event. If there's no @cancel event, the cancel button should not be visible.
Is there a way to check if a component has event listener attached to it?
Currently I do:
<template>
  <form>
    <button v-if="cancelEventPassed" @click="$emit('cancel')">Cancel</button>
  </form>
</template>
And call it like this:
<Form :cancelEventPassed="true" @cancel="handle_cancel" />
either
<Form/>
Is it possible to achieve this without using any additional property like cancelEventPassed?
Solution 1:[1]
When there are listeners attached to a component they are available in the $listeners property of the component.
You can use that property to determine if a specific listener is available. For example, here is a computed property that checks for the existence of a cancel listener.
computed:{
  hasCancelListener(){
    return this.$listeners && this.$listeners.cancel
  }
}
And here is an example of that used in a component.
console.clear()
Vue.component("CustomForm", {
  template:`
    <div>
      <h1>Custom Form</h1>
      <button v-if="hasCancelListener" @click="$emit('cancel')">I have a listener!</button>
    </div>
  `,
  computed:{
    hasCancelListener(){
      return this.$listeners && this.$listeners.cancel
    }
  },
})
new Vue({
  el: "#app",
  methods:{
    onCancel(){
      alert('canceled')
    }
  }
})
<script src="https://unpkg.com/[email protected]"></script>
<div id="app">
  <custom-form @cancel="onCancel"></custom-form>
  <hr>
  <custom-form></custom-form>
</div>
Solution 2:[2]
In Vue 3, the $listeners object has been removed. The listeners are now part of the $attrs object and are prefixed with on.
In order to check if a particular listener is present or not in a child component, you can do:
computed: {
  hasCancelListener() : boolean {
    return (this.$attrs && this.$attrs.onCancel) as boolean
  }
}
The child component is called as:
<custom-form @cancel="onCancel"></custom-form>
    					Solution 3:[3]
You can check if listener exists like that:
this._events['listener-name']
Solution 4:[4]
If you're here looking for Vue 3 script setup or setup function solution, you can check the attrs key in getCurrentInstance function
<template>
  <form>
    <button @click="$emit('cancel')">Cancel</button>
  </form>
</template>
<custom-form @cancel="onCancel"></custom-form>
onMounted(() => {
  const instance = getCurrentInstance() // only available inside lifecycle hooks
  console.log(instance?.attrs?.onCancel)
})
    					Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source | 
|---|---|
| Solution 1 | Bert | 
| Solution 2 | |
| Solution 3 | Tadas Majeris | 
| Solution 4 | wobsoriano | 
