[Vuejs]-Delete selected table row VueJS?

1👍

You must to fix two points. In your HTML template you must fix this:

<v-btn @click="deleteRow(selected)">Delete Selected</v-btn>

And you must to fix you mutation:

mutations: {
  deleteRow(state, selectedRows) {
    for (let row of selectedRows) {
      let index = state.desserts.findIndex(el => el.name === row.name);
      state.desserts.splice(index, 1);
    }
  },
},

I will post all code, if you have doubts.

<template>
  <div>
    <v-data-table
      v-model="selected"
      :headers="getHeaders"
      :items="getDesserts"
      hide-actions
      select-all
      item-key="name"
    >
      <template v-slot:headers="props">
        <tr>
          <th>
            <v-checkbox
              :input-value="props.all"
              :indeterminate="props.indeterminate"
              primary
              hide-details
              @click.stop="toggleAll"
            ></v-checkbox>
          </th>
          <th v-for="header in props.headers" :key="header.text">
            <v-icon small>arrow_upward</v-icon>
            {{ header.text }}
          </th>
        </tr>
      </template>
      <template v-slot:items="props">
        <tr :active="props.selected" @click="props.selected = !props.selected">
          <td>
            <v-checkbox :input-value="props.selected" primary hide-details></v-checkbox>
          </td>
          <td>{{ props.item.name }}</td>
          <td>{{ props.item.calories }}</td>
          <td>{{ props.item.fat }}</td>
        </tr>
      </template>
    </v-data-table>
    <v-btn @click="deleteRow(selected)">Delete Selected</v-btn>
  </div>
</template>

<script>
import { mapGetters, mapMutations } from 'vuex';
export default {
  name: 'HelloWorld',
  data() {
    return {
      selected: [],
    };
  },
  computed: {
    ...mapGetters({
      getHeaders: 'getHeaders',
      getDesserts: 'getDesserts',
    }),
  },
  methods: {
    ...mapMutations({
      deleteRow: 'deleteRow',
    }),
    toggleAll() {
      if (this.selected.length) this.selected = [];
      else this.selected = this.getDesserts.slice();
    },
  },
};
</script>
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    headers: [
      { text: 'Dessert (100g serving)', align: 'left', value: 'name' },
      { text: 'Calories', value: 'calories' },
      { text: 'Fat (g)', value: 'fat' },
    ],
    desserts: [
      { value: false, name: 'Lollipop', calories: 159, fat: 6.0 },
      { value: false, name: 'Marshamallow', calories: 262, fat: 16.0 },
    ],
  },
  getters: {
    getHeaders: state => state.headers,
    getDesserts: state => state.desserts,
  },
  mutations: {
    deleteRow(state, selectedRows) {
      for (let row of selectedRows) {
        let index = state.desserts.findIndex(el => el.name === row.name);
        state.desserts.splice(index, 1);
      }
    },
  },
  actions: {},
  modules: {},
});

3👍

You just need 2 simple changes…

1. change the Vuex mutation:

  mutations: {
    deleteRow(state, selected) {
      state.desserts = state.desserts.filter(el => !selected.includes(el));
    }
  }

2. update @click to pass in selected:

  <v-btn @click="deleteRow(selected)">Delete Selected</v-btn>

Working demo: https://codeply.com/p/e0kSBOhyUE

codesandbox

0👍

You are not passing the selected name to mutations. For that reason the below code will return -1, and thus removing the last item from the array.

//In HelloWorld.vue, name is not passed to function
<v-btn @click="deleteRow">Delete Selected</v-btn>
//name is not passed to the state.
deleteRow(state, name) {
  let index = state.desserts.findIndex(el => el.name === name);
  console.log(index) //will log -1   
  state.desserts.splice(index, 1);
}

A quick solution will be pass name from the origin

<v-btn @click="deleteRow(selected[0].name)">Delete Selected</v-btn>

But this will delete only one element from the selected, where selected is the array of items that are being selected from the table. And the expected behaviour is that all the selected items will be deleted from the array. Either you can pass all the selected items to the delete row function as deleteRow(selected) or You could modify your store to record the selected items.

state: {
  headers: {...},
  desserts: {...},
  selected: []
},
mutations: {
  setSelected(state, items){
    state.selected = items;
  },
  deleteRow(state, name) {
    const selectedItems = state.selected
    for(var i=0;i<selectedItems.length;i++){
      let index = state.desserts.findIndex(el => el.name === selectedItems[i]);
      state.desserts.splice(index, 1);
    }
  }
}

And In your HelloWorld.vue

<template>
  <div>
    <v-data-table
      v-model="selected"
      :headers="getHeaders"
      :items="getDesserts"
      hide-actions
      select-all
      item-key="name"
    >
      <template v-slot:headers="props">
        <tr>
          <th>
            <v-checkbox
              :input-value="props.all"
              :indeterminate="props.indeterminate"
              primary
              hide-details
              @click.stop="toggleAll"
            ></v-checkbox>
          </th>
          <th v-for="header in props.headers" :key="header.text">
            <v-icon small>arrow_upward</v-icon>
            {{ header.text }}
          </th>
        </tr>
      </template>
      <template v-slot:items="props">
        <tr :active="props.selected" @click="props.selected = !props.selected">
          <td>
            <v-checkbox :input-value="props.selected" primary hide-details></v-checkbox>
          </td>
          <td>{{ props.item.name }}</td>
          <td>{{ props.item.calories }}</td>
          <td>{{ props.item.fat }}</td>
        </tr>
      </template>
    </v-data-table>
    <v-btn @click="deleteRow">Delete Selected</v-btn>
  </div>
</template>

<script>
import { mapGetters, mapMutations } from "vuex";
export default {
  name: "HelloWorld",
  data(){
    return {
      selected: []
    }
  },
  watch: {
    selected: function(n, o){
      this.setSelected(n) //selected is watched, and when ever its changed store will be updated.
    }
  },
  computed: {
    ...mapGetters({
      getHeaders: "getHeaders",
      getDesserts: "getDesserts"
    })
  },
  methods: {
    ...mapMutations({
      setSelected: "setSelected", //Added a new method from mutation
      deleteRow: "deleteRow",

    }),
    toggleAll() {
      if (this.selected.length) this.selected = [];
      else this.selected = this.getDesserts.slice();
    }
  }
};
</script>



Leave a comment