Home » vue » How to handle a slot's onClick event in VueJS

How to handle a slot's onClick event in VueJS

Posted by: admin November 26, 2021 Leave a comment

Questions:

I’m trying to build a reusable Dialog without having to make use of any refs to interact with the dialog. It has 2 named slots. activator and content.

activator can be any element that when clicked will cause the dialog to open (some text, an icon, etc). content is the content to display in the dialog.

I think that I have created everything correctly however the on Click handler doesn’t seem to work on the activator slot. The dialog does not show. See code below:

PopupDialog.vue

<template>
  <div>
    <div>
      <slot @click="dialog = true" name="activator" />
    </div>

    <v-dialog
      v-model="dialog"
      persistent
      max-width="400"
    >
      <slot name="content" />
    </v-dialog>
  </div>
</template>

<script>
export default {
  name: "PopupDialog",
  data: () => ({
    dialog: false,
  }),
};
</script>

And then I try using the component like this:

  <PopupDialog>
    <template v-slot:activator>
      <span>
        Add Member
      </span>
    </template>

    <template v-slot:content>
      <span>
        Content to show in dialog
      </span>
    </template>
  </PopupDialog>

When I click the span text nothing happens, why is that? Is it not possible to use event listeners on slots? How would I be able to make this work?

Answers:

Nothing happens because you can’t apply an event listener to slot children like that.

Instead, you could pass a method as a slot prop to the activator slot, so that children can bind a click event handler to that method:

<slot name="activator" :onClick="onClick" />
export default {
  name: 'PopupDialog',
  methods: {
    onClick() {
      this.dialog = true
    }
  }
}

Then use it like this:

<PopupDialog>
  <template v-slot:activator="{ onClick }">
    <span @click="onClick"> Add Member </span>
  </template>
</PopupDialog>

demo