0

I have a VueJS 3 application with two Vue components (.vue files) and Vue 3 Composition API syntax. The first one contains a radio list that will be used to apply a filter to the second component (imported inside the first component) that contains a Vue3 client datatable. This datatable is the Vue3 version of this datatable : https://github.com/matfish2/vue-tables-2.

My goal is to send a filter event (when I click on a radio element) from the parent component to the datatable inside the child component by using the customFilters option of the datatable. This event should apply a custom filter to the data inside v-tables-3 according to the value of the selected radio button.

Note that the custom event is passed from parent to child using Vue 3 props.

According to the columnFilters documentation, I can add a customFilters inside the datatable options by doing something like that:

customFilters: [{
  name: 'alphabet',
  callback: function(row, query) {
    return row.name[0] == query;
  }
}]

and then emit the event using either

Event.$emit('vue-tables.filter::alphabet', query);

or (Vue 3 version)

EventBus.emit('vue-tables.filter::alphabet', query);

I tried to apply the same function as the documentation, but I never managed to make it works.

I then tried to use Mitt directly to try passing an event from a component to another. I can emit an event from the parent to the child and display the content of the query, but only by hard coding emitter.on(event_name, e=> console.log(e) inside the OnMounted function, and it doesn't looks like the thing to do (it is not written in the documentation). Moreover, the customFilter is completly ignored.

my main.js file :

import { createApp } from "vue";
import App from "./App.vue";
const app = createApp(App);

// datatables
import { ClientTable, EventBus } from "v-tables-3";

// Mitt
import mitt from 'mitt';
const emitter = mitt();
app.config.globalProperties.emitter = mitt();

app.use(ClientTable).use(EventBus).use(emitter).mount("#app");

my parent Vue component :

<template>
<div class="col-2 layout-spacing">
    <div class="radio-classic radio-primary mb-3 custom-control custom-radio">
        <input type="radio" class="custom-control-input" id="radio_id_1" name="radio_name" value="value_1" required @change="refreshDatatable($event)"/>
        <label class="custom-control-label" :for="radio_id_1">Value 1</label>
    </div>
    <div class="radio-classic radio-primary mb-3 custom-control custom-radio">
        <input type="radio" class="custom-control-input" id="radio_id_2" name="radio_name" value="value_2" required @change="refreshDatatable($event)"/>
        <label class="custom-control-label" :for="radio_id_2">Value 2</label>
    </div>
    <!-- More radio inputs -->
    />
</div>

<div class="col-10 layout-spacing">
    <datatable v-bind:custom_filters="family_filters"/>
</div>

</template>

<script setup>
    import { getCurrentInstance } from 'vue';
    import { EventBus } from 'v-tables-3';
    import datatable from './child_component.vue';

    const internalInstance = getCurrentInstance();
    const emitter = internalInstance.appContext.config.globalProperties.emitter;

    const family_filters = [{
        name: 'fa_filter',
        callback: function (row, query) {
            return row.name[0] == query;
        }
    }];
    const refreshDatatable = (event) => {
        emitter.emit('fa_filter_mitt', event.target.value); // Mitt version
        EventBus.emit('vue-tables.filter::fa_filter', event.target.value); // v-tables EventBus version
    }
</script>

my child component

<template>
    <v-client-table :data="items" :columns="columns" :options="table_option"/>
</template>

<!-- Get props from parent Component -->
<script>
    export default {
        props: ['custom_filters'],
    };
</script>

<script setup>
    import { onMounted, getCurrentInstance } from 'vue';
    import { EventBus } from 'v-tables-3';

    const internalInstance = getCurrentInstance();
    const emitter = internalInstance.appContext.config.globalProperties.emitter;

    const table_option = ref({
        (...)
        customFilters: __props.custom_filters === undefined ? [] : __props.custom_filters,
    });

    onMounted(() => {
        emitter.on('fa_filter_mitt', e=> console.log('test Mitt : ', e));
        EventBus.on('vue-tables.filter::fa_filter', e=> console.log('test datatable EventBus : ', e));
    });
</script>

How can I have the event transmitted from parent to child ?

Note that emitter only contains the 'fa_filter_mitt' event and nothing else, the customFilters option seems ignored.

Laurent
  • 1
  • 1

0 Answers0