0

I'm trying to figure how you can pick up an event that is triggered inside the <slot/> component.

Here is my component

<template>
  <button @click"$emit('event')">Submit</button>
</template>

It emits an event I want to capture in the parent layout's slot.

<template>
  <slot @event="doThis"/>
</template>

How do I achieve this. Some of my reading has lead me to scoped slots but I'm not 100% sure.

jermainecraig
  • 311
  • 4
  • 20

2 Answers2

2

In Vue3, you can expose slot properties (slotProps) and thus template methods like this.

MyComponent

<template>
    <!-- action will be exposed in slotProps -->
    <slot name="mySlotName" :action="myDefaultAction">
        <!-- default slot component, <button> for example? -->
        <button @click="myDefaultAction($event)" />
    </slot>
</template>

<script>
    // ... export default data etc. ...
    methods: {
        myDefaultAction(event) {
            // do something
        }
    // ...
</script>

How to use this?

AnotherComponent (using MyComponent)

<template>
    <MyComponent>
        <!-- destructuring slotProps -->
        <!-- here action() == myDefaultAction() -->
        <template #mySlotName="{ action }">
           <!-- define another behavior or layout for the slot -->
            <button @click="anotherBehavior($event, action)" />
        </template>
    </MyComponent>
    <!-- Other components... -->
</template>

<script>
    // ... export default data etc. ...
    methods: {
        anotherBehavior(event, action) {
            // do something else
            // ...
            // or call the default action if necessary 
            action(event);
        }
   // ...
</script>

Docs about Slot for Vue3

Paul
  • 1,410
  • 1
  • 14
  • 30
0

Use Event Bus to flash an event so any component can catch it if he listens as below :

In event-bus.js

import Vue from 'vue';
export const EventBus = new Vue();

In your parent and child components import the event bus file : import { EventBus } from './event-bus.js';

In your parent component, listen to the event :

methods:
{
    const clickHandler = function(params) { /*Do whatever */ }
}
mounted()
{
   EventBus.$on('event', clickHandler);
}

In your child component, you can trigger the event as below :

<template>
  <button @click="EventBus.$emit('event', params)">Submit</button>
</template>
Samidjo
  • 2,315
  • 30
  • 37
  • 2
    This works if there's not another solution available. The disadvantage is that events that would otherwise be "local" are now "global" which can lead to maintenance/debugging headaches down the road if not handled carefully. – Jason Smith Jan 10 '20 at 12:43