yavuzkavus
yavuzkavus

Reputation: 1266

Is it possible to access event listeners from component in Vue.js 2

I have a custom component in Vue.js(2) as:

Vue.component("modal-panel", {
    props: {
        id: {
            required: true
        },
        title: {} ,
        size: {
            validator: function(value) {
                return !value || value=="lg" || value=="sm";
            }
        }, 
        confirmLabel: {
            "default": "Yes",
        }, 
        closeLabel: {
            "default": "No"
        },
        confirm: {
            type: Function
        }
    },
    //...
    template: `
        //...
        <button type="button" class="btn btn-primary confirm" data-dismiss="modal" v-on:click="$emit('confirm')" v-if="confirm">{{confirmLabel}}</button>
        //...
    `
}

And this is the code using component

<modal-panel title="New User" id="userModal" @confirm="doSomething">...</modal-panel>

As seen from the component code, confirm has been inserted into the props and on the button code in the template there is a conditional rendering according to whether confirm listener attached or not. However, button is not rendered. I checked component dom and properties, but there is not such an info.

Is it possible to make conditional rendering according to whether a specific listener attached to component in vue.js?

Thanks.

Upvotes: 4

Views: 8116

Answers (2)

Bert
Bert

Reputation: 82459

Since Vue 2.4, Vue components have a $listeners property.

Contains parent-scope v-on event listeners (without .native modifiers).

This is documented here. You can determine whether or not the parent is listening to a particular event by examining the $listeners property.


**Original Answer**

It's not generally good practice for a component to reach out of itself to determine things.

I would recommend instead that you have a confirm callback property. You can pass a function in as a property. Then you can decide to show/hide the button on whether you received the callback or not.

Vue.component("modal",{
  props:["confirm"],
  template: `
    <div>
      <h1>Modal</h1>
      <button v-if="confirm" @click="confirm">Confirm</button>
    </div>
  `
})

Example.

Edit

You can determine if there is a handler defined on a component for a given event, but it requires examining an internal Vue property, and you should only use this at your own risk.

Vue.component("modal",{
  template: `
    <div>
      <h1>Modal</h1>
      <button v-if="hasConfirmHandler" @click="$emit('confirm')">Confirm</button>
    </div>
  `,
  computed:{
    hasConfirmHandler(){
      return !!this._events["confirm"]
    }
  }
})

The _events property of the component will contain the handler, if a handler is defined from the parent.

Example.

Upvotes: 5

dfsq
dfsq

Reputation: 193261

You need to bind your function with v-bind or : instead of just passing it as a string. So use :confirm syntax:

<modal-panel title="New User" id="userModal" :confirm="doSomething"></modal-panel>

Then in component template simply use v-on:click="confirm()":

<button type="button" class="btn btn-primary confirm" data-dismiss="modal" 
  v-on:click="confirm()" 
  v-if="confirm">
  {{confirmLabel}}
</button>

Upvotes: 0

Related Questions