As of date of posting, I cannot find any documentation to use the \"custom filter\" prop in data tables.
I just want to create a custom filter to filter my data table by
You can also go the customFilter approach like this, I've restricted the search to the type field.
new Vue({
el: '#app',
data() {
return {
food: [
{ name: 'Bakchoi', type: 'vegetable', calories: 100 },
{ name: 'Pork', type: 'meat', calories: 200 },
{ name: 'Chicken Thigh', type: 'meat', calories: 300 },
{ name: 'Watermelon', type: 'fruit', calories: 10 },
],
headers: [
{ text: 'Name', align: 'left', value: 'name' },
{ text: 'Food Type', align: 'left', value: 'type' },
{ text: 'Calories', align: 'left', value: 'calories' },
],
search: '',
};
},
methods: {
customFilter(items, search, filter) {
search = search.toString().toLowerCase()
return items.filter(row => filter(row["type"], search));
}
}
})
<script src="https://unpkg.com/vue@2.4.2/dist/vue.js"></script>
<script src="https://unpkg.com/vuetify@0.15.2/dist/vuetify.js"></script>
<link rel="stylesheet" href="https://unpkg.com/vuetify@0.15.2/dist/vuetify.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons">
<div id="app">
<v-app>
<v-select
label="Food Type"
:items="['vegetable', 'meat', 'fruit']"
v-model="search"
></v-select>
<v-data-table
:headers="headers"
:items="food"
:search="search"
:custom-filter="customFilter"
hide-actions
>
<template slot="items" scope="{ item }">
<td>{{ item.name }}</td>
<td>{{ item.type }}</td>
<td>{{ item.calories }}</td>
</template>
</v-data-table>
</v-app>
</div>
Looking at the code on Github1, it looks like the customFilter
prop is used to overwrite the default method used to determine how the filter
prop is applied to the items in the table.
The default customFilter
method applies the filter
function to each property name of each item object and filters out any items that don't include one property name that passes the filter:
customFilter: { type: Function, default: (items, search, filter) => { search = search.toString().toLowerCase() return items.filter(i => ( Object.keys(i).some(j => filter(i[j], search)) )) } },
You might want to overwrite this function if you wanted to prevent any columns from being included in the filter or if there were specific rows that you always wanted to prevent from being filtered out.
You'll notice that the method also depends on the search
prop, which must be a string.
All that said, you really don't need to use that prop for what you want to do. You should just make a computed property to filter the items based on your dropdown value and pass that computed property as the items
prop.
Here's an example:
new Vue({
el: '#app',
data() {
return {
food: [
{ name: 'Bakchoi', type: 'vegetable', calories: 100 },
{ name: 'Pork', type: 'meat', calories: 200 },
{ name: 'Chicken Thigh', type: 'meat', calories: 300 },
{ name: 'Watermelon', type: 'fruit', calories: 10 },
],
headers: [
{ text: 'Name', align: 'left', value: 'name' },
{ text: 'Food Type', align: 'left', value: 'type' },
{ text: 'Calories', align: 'left', value: 'calories' },
],
foodType: null,
};
},
computed: {
filteredItems() {
return this.food.filter((i) => {
return !this.foodType || (i.type === this.foodType);
})
}
}
})
<script src="https://unpkg.com/vue@2.4.2/dist/vue.js"></script>
<script src="https://unpkg.com/vuetify@0.15.2/dist/vuetify.js"></script>
<link rel="stylesheet" href="https://unpkg.com/vuetify@0.15.2/dist/vuetify.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons">
<div id="app">
<v-app>
<v-select
label="Food Type"
:items="['vegetable', 'meat', 'fruit']"
v-model="foodType"
></v-select>
<v-data-table
:headers="headers"
:items="filteredItems"
hide-actions
>
<template slot="items" scope="{ item }">
<td>{{ item.name }}</td>
<td>{{ item.type }}</td>
<td>{{ item.calories }}</td>
</template>
</v-data-table>
</v-app>
</div>
In my case I have 2 different way of filtering which are search bar and drop down. I tried to use custom-filter
for both of them, but it doesn't work, so I came up with another approach
<v-text-field v-model="search" label="Label"></v-text-field>
<v-select
v-model="select"
:items="food"
item-text="type"
item-value="type"
:label="Types"
@change="filterFoodUsingDropDown"
>
</v-select>
<v-data-table
:search="search"
:headers="headers"
:items="food"
:custom-filter="filterFoodUsingSearchbar"
>
data() {
return {
food: [
{ name: 'Bakchoi', type: 'vegetable', calories: 100 },
{ name: 'Pork', type: 'meat', calories: 200 },
{ name: 'Chicken Thigh', type: 'meat', calories: 300 },
{ name: 'Watermelon', type: 'fruit', calories: 10 },
],
headers: [
{ text: 'Name', align: 'left', value: 'name' },
{ text: 'Food Type', align: 'left', value: 'type' },
{ text: 'Calories', align: 'left', value: 'calories' },
],
search: '',
select: '',
};
},
methods: {
filterFoodUsingSearchbar(items, search, filter) {
// Condition
}
filterFoodUsingDropDown() {
if (this.select !== '') {
// In this case I use vuex to store the original data of the
food so that all the data is still exist even we filtered it out
this.food = this.$store.state.food.filter((item) => item.type === this.select)
}
}