Search code examples
javascriptvue.jsvuejs2vue-component

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

  • 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>