Emitted event doesn't call parent method in Vue JS component

I have two nested Vue JS components: 'States - Parent' => 'admin-data-table - Child'.

Inside the child component there is a button that emits an event back to the parent when clicked:

Child component - admin-data-table:

<template>
    <v-data-table :ref="modelName + 'Table'" :value="selectedList" @input="$emit('update:selectedList', $event)" :headers="dataTable.headers" :items="collection" :pagination.sync="dataTable.pagination" select-all item-key="id" class="elevation-1" >
        <template v-slot:items="props">
            <v-btn v-if="!props.item.active" title="Enable" color="success" small @click.prevent="$emit('toggle-active', props.item.id)"><v-icon>domain</v-icon>Enable</v-btn>
            <v-btn v-else title="Disable" color="error" small @click.prevent="$emit('toggle-active', props.item.id)"><v-icon>domain_disabled</v-icon>Disable</v-btn>
        </template>
    </v-data-table>
</template>

Inside parent component:

<admin-data-table @toggle-active="toggleActive"></admin-data-table>

This works fine, and the emitted 'toggle-active' event bubbles up to the parent method properly.


However I want to change this to incorporate a named slot for the buttons:

admin-data-table component [child]:

<template>
    <v-data-table :ref="modelName + 'Table'" :value="selectedList" @input="$emit('update:selectedList', $event)" :headers="dataTable.headers" :items="collection" :pagination.sync="dataTable.pagination" select-all item-key="id" class="elevation-1" >
        <template v-slot:items="props">
            <slot name="rowBtns" v-bind:item="props.item"></slot>
        </template>
    </v-data-table>
</template>

Inside parent component:

<admin-data-table @toggle-active="toggleActive">
        <template #rowBtns="props">
            <v-btn v-if="!props.item.active" title="Enable" color="success" small @click.prevent="$emit('toggle-active', props.item.id)"><v-icon>domain</v-icon>Enable</v-btn>
            <v-btn v-else title="Disable" color="error" small @click.prevent="$emit('toggle-active', props.item.id)"><v-icon>domain_disabled</v-icon>Disable</v-btn>
        </template>
    </admin-data-table>

Now when I click on the button the toggleActive method in the parent component is no longer called when the toggle-active event is emitted. I confirmed the event is still being emitted with the correct payload when the button is pressed.

Why is this not triggering the toggleActive parent component function anymore?

<admin-data-table @toggle-active="toggleActive">

Upvotes: 3

Views: 2709

Answers (1)

Decade Moon
Decade Moon

Reputation: 34286

This is explained in Compilation Scope.

Your <v-btn> exists within the template of the parent, not the child, so you are actually calling $emit on the parent component instance and not the child.

You do not need to use events for this situation since the parent component is managing the button itself, so you can directly call the toggleActive method from the button click event like this:

@click.prevent="toggleActive(props.item.id)"

Upvotes: 2

Related Questions