1
votes

I need to remove an item (row) from a Vuetify data table. I'm binding the data table's items prop to a computed variable called screens using mapState from vuex.

<v-data-table
    ref="dataTable"
    v-bind:headers="headers"
    v-bind:items="screens"
    v-bind:search="search"
    :loading="loading"
>
    <template slot="items" slot-scope="props">
        <tr @click="props.expanded = !props.expanded">
            <td>{{ props.item.name }}</td>
            <!-- etc -->
        </tr>
    </template>
    <template slot="expand" slot-scope="props">
        <screen-edit-form :screen-data="props.item"></screen-edit-form>
    </template>
    <template slot="pageText" slot-scope="{ pageStart, pageStop }">
        From {{ pageStart }} to {{ pageStop }}
    </template>
</v-data-table>
...

Snippet from computed vars

/**
 * Automated the fetching of screen data.
 */
 computed: mapState( {

    screens: state => state.Screens.data

 } ),

Mutation in vuex

/**
 * Create an unset function using Lodash
 * @param state
 * @param payload
 */
unsetById: ( state, payload ) => {

    // Remove the item
    _.remove( state.data, { id: payload.id } );

    // Emit an event to the event bus
    EventBus.$emit( 'screen-deleted' );

}

The data table uses a template slot named items with a slot-scope called props. However, whenever I mutate screens, I can see that the items array is altered properly (the item I removed from the screens array has, indeed, gone) but I have no reactivity on the DOM.

I'm aware from the docs that if I want a two-way binding I need to sync the props. I have tried using the .sync modifier on the v-bind:items and emitting a change using this.$refs.dataTable.$emit( 'update:items', this.screens ); to no avail.

Any help with obtaining two-way binding with slot props would be much appreciated. The ultimate aim is be able to remove items from the data table and have it reflected immediately on the DOM.

Thanks.

2

2 Answers

1
votes

Thanks @jacek of Vuetify chat. Turns out mutations also follow Vue's Reactivity Rules. I simply need to import Vue from 'vue' (if not imported already) and use Vue's delete method in my unset function.

/**
 * Create an unset function using Lodash
 * @param state
 * @param payload
 */
unsetById: ( state, payload ) => {

    // Remove the item
    Vue.delete( state.data, _.findIndex( state.data,{ id: payload.id } ) );

    // Emit an event to the event bus
    EventBus.$emit( 'screen-deleted' );

}
0
votes

If u want to have it immediately reflected on the DOM you can try splicing or filtering the array where is your data.

I personally use filtering if I want to bulk delete and splicing for single deletes. If you want to splice, first you have to get the index of your object in an array with indexOf, so...

const index = this.items.indexOf(object)
this.items.splice(index, 1)