Verba
Verba

Reputation: 388

Vue Tables 2 - Custom filters

I'm trying to use this https://github.com/matfish2/vue-tables-2 with Vue 2.1.8.

And it's working perfectly BUT I need to use custom filters to format some fields based on their value etc.

In options I have this:

customFilters: [
{
  name:'count',
  callback: function(row, query) {
    console.log('see me?'); // Not firing this
    return row.count[0] == query;
}
}
]

In the docs it says I have to do this:

Using the event bus:

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

But I have no idea where to put this? I tried many places. For example in my axios success callback but nothing.

I guess this is very basic and I should know this but I don't. So if someone could tell me where to put that event bus staff would be awesome!

Upvotes: 9

Views: 20508

Answers (4)

Kirk Ross
Kirk Ross

Reputation: 7153

Updated working fiddle for anyone who wants to play around. I still am not sure how to make it work with nested, single page components.

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

Upvotes: 0

Jiro Matchonson
Jiro Matchonson

Reputation: 981

Hide default filter and per page seletbox and defining one new filter 'manual_agent' .

        optionsTable: {
            customFilters: ['manual_agent'],
            filterable: false,
            perPageValues: []
        },

Hiding because there is not 'slot' option to be able add new custom filters between default one and per page select, and default one is also not much repsonsive. Below example is for server table implementation.

Method to be used globally for custom filters :

toggleFilter: function(filterName, $event) {
                this.$refs.serverTableRef.setPage(1);
                setTimeout(function () {
                    let searchItem = '';
                    if (typeof $event === 'string') { searchItem = $event; } else { searchItem = $event.target.value; }
                    let table = this.$refs.serverTableRef;
                    table.customQueries[filterName] = searchItem;
                    table.getData();
                }.bind(this), 1000);
            }

For this to work we have to have defined ref name on our v-server table like this :

<v-server-table ref="serverTableRef"

Now in template new custom selectbox filter (v-model just points to custom variable defined in data)

<select name="typeoftrip" v-model="agentFilter" @change="toggleFilter('manual_agent', agentFilter)">

And custom filter that will replace default filter we lost by dissabling it. (it used 'query' name so we use same)

<input name="typeoftrip" v-model="mainQuery" v-on:keyup="toggleFilter('query', mainQuery)">

And new custom select for our own per page select

            <select v-model="limitFilter"  @change="$refs.serverTableRef.setLimit($event.target.value)" >
                <option value="10">10</option>
                <option value="25">25</option>
                <option value="50">50</option>
            </select>

Upvotes: 0

Turbo
Turbo

Reputation: 392

I found this lesson to help me the best. https://github.com/ratiw/vuetable-2-tutorial/wiki/lesson-13

Summary: You should emit events with vue-events package or compute properties with Vuex (recommended). You want to use the :append-params="moreParams" on vuetable which is a feature of vuetable2 that will append to api-url along with pagination values (separate from these params). I am using Vuex so I make moreParams a computed property of the vuetable. It uses this.$store.getters.moreParams which is my Vuex getter as I have multiple search fields. This is reactive to my Vuex commits from input field handlers.

    computed: {
      moreParams() {
        return this.$store.getters.moreParams
      },
    },

Otherwise you could use a $store.stage.property. I have a watch on moreParams which refreshes the table with the new query:

    watch: {
      moreParams(newVal, oldVal) {
        this.$nextTick(() => {
          this.$refs.vuetable.refresh()
        })
      },
    },

Upvotes: 0

AWolf
AWolf

Reputation: 8970

The docs could be describing this better. It's a bit difficult to understand.

You need to import the named export Event of vue-tables-2, so you have the event bus of the table and emit the custom event in your custom click handler.

In the demo it's available on global object. In ES6 you'll import it as described in the docs with import {ServerTable, ClientTable, Event} from 'vue-tables-2';

Please have a look at the alphabet filter demo below or in this fiddle.

The demo is similar to the vue-tables-1 demo fiddle that you can find here.

// Vue.use(VueTables)
const ClientTable = VueTables.ClientTable
const Event = VueTables.Event // import eventbus

console.log(VueTables);
Vue.use(ClientTable)

new Vue({
  el: "#people",
  methods: {
    applyFilter(letter) {
      this.selectedLetter = letter;
      Event.$emit('vue-tables.filter::alphabet', letter);
    }
  },
  data() {
    return {
      letters: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'],
      selectedLetter: '',
      columns: ['id', 'name', 'age'],
      tableData: [{
        id: 1,
        name: "John",
        age: "20"
      }, {
        id: 2,
        name: "Jane",
        age: "24"
      }, {
        id: 3,
        name: "Susan",
        age: "16"
      }, {
        id: 4,
        name: "Chris",
        age: "55"
      }, {
        id: 5,
        name: "Dan",
        age: "40"
      }],
      options: {
        // see the options API
        customFilters: [{
          name: 'alphabet',
          callback: function(row, query) {
            return row.name[0] == query;
          }
        }]
      }
    }
  }
});
#people {
  text-align: center;
  width: 95%;
  margin: 0 auto;
}
h2 {
  margin-bottom: 30px;
}
th,
td {
  text-align: left;
}
th:nth-child(n+2),
td:nth-child(n+2) {
  text-align: center;
}
thead tr:nth-child(2) th {
  font-weight: normal;
}
.VueTables__sort-icon {
  margin-left: 10px;
}
.VueTables__dropdown-pagination {
  margin-left: 10px;
}
.VueTables__highlight {
  background: yellow;
  font-weight: normal;
}
.VueTables__sortable {
  cursor: pointer;
}
.VueTables__date-filter {
  border: 1px solid #ccc;
  padding: 6px;
  border-radius: 4px;
  cursor: pointer;
}
.VueTables__filter-placeholder {
  color: #aaa;
}
.VueTables__list-filter {
  width: 120px;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue-tables-2.min.js"></script>
<div id="people">
  <button @click="applyFilter(letter)" class="btn btn-default" v-for="letter in letters" :class="{active: letter==selectedLetter}">
    {{letter}}
  </button>
  <button  class="btn btn-default" @click="applyFilter('')">
  clear
  </button>
  <v-client-table :data="tableData" :columns="columns" :options="options"></v-client-table>
</div>

Upvotes: 16

Related Questions