Filtering

The native Vue Grid by Kendo UI provides diverse filtering options for displaying Grid records which meet specified criteria.

Getting Started

To enable filtering:

  1. Set the filterable and filter options of the Grid.
  2. Handle the filterchange event of the Grid, and filter the data manually by applying the filter from the argument of the event.

Filter Row

By default, when filtering is enabled, the Grid renders a filter row in its column headers. Based on the type of data the columns contain, the filter row displays textboxes in each column header where the user can filter string, numeric, or date inputs.

<div id="vueapp" class="vue-app">
    <Grid
        :data-items="products"
        :filterable="true"
        :filter="filter"
        @filterchange="filterChange"
        :columns="columns">
    </Grid>
</div>
import Vue from 'vue';
import { Grid, GridToolbar, GridNoRecords } from '@progress/kendo-vue-grid';
import { filterBy, CompositeFilterDescriptor } from '@progress/kendo-data-query';
import { sampleProducts } from './app/products';

Vue.component('Grid', Grid);

new Vue({
    el: '#vueapp',
    data: function () {
        return {
            filter: {
                logic: "and",
                filters: [
                    { field: "UnitPrice", operator: "neq", value: 18 },
                    { field: "FirstOrderedOn", operator: "gte", value:new Date("1996-10-10") }
                ]
            }
        };
    },
    computed: {
        products: function() {
            return filterBy(sampleProducts, this.filter);
        },
        columns: function () {
            return [
                { field: 'ProductID', filterable:false, title: 'Product ID', width:'50px'},
                { field: 'ProductName', title: 'Product Name' },
                { field: 'FirstOrderedOn', filter:'date', title: 'First Ordered On'},
                { field: 'UnitPrice', filter:'numeric', title: 'Unit Price'},
                { field: 'Discontinued', filter:'boolean', title: 'Discontinued'}
            ]
        }
    },
    methods: {
        filterChange: function(ev) {
            this.filter = ev.filter;
        }
    }
});
const sampleProducts = [
    {
        "ProductID": 1,
        "ProductName": "Chai",
        "SupplierID": 1,
        "CategoryID": 1,
        "QuantityPerUnit": "10 boxes x 20 bags",
        "UnitPrice": 18,
        "UnitsInStock": 39,
        "UnitsOnOrder": 0,
        "ReorderLevel": 10,
        "Discontinued": false,
        "Category": {
            "CategoryID": 1,
            "CategoryName": "Beverages",
            "Description": "Soft drinks, coffees, teas, beers, and ales"
        },
        "FirstOrderedOn": new Date(1996, 8, 20)
    },
    {
        "ProductID": 2,
        "ProductName": "Chang",
        "SupplierID": 1,
        "CategoryID": 1,
        "QuantityPerUnit": "24 - 12 oz bottles",
        "UnitPrice": 19,
        "UnitsInStock": 17,
        "UnitsOnOrder": 40,
        "ReorderLevel": 25,
        "Discontinued": false,
        "Category": {
            "CategoryID": 1,
            "CategoryName": "Beverages",
            "Description": "Soft drinks, coffees, teas, beers, and ales"
        },
        "FirstOrderedOn": new Date(1996, 7, 12)
    },
    {
        "ProductID": 3,
        "ProductName": "Aniseed Syrup",
        "SupplierID": 1,
        "CategoryID": 2,
        "QuantityPerUnit": "12 - 550 ml bottles",
        "UnitPrice": 10,
        "UnitsInStock": 13,
        "UnitsOnOrder": 70,
        "ReorderLevel": 25,
        "Discontinued": false,
        "Category": {
            "CategoryID": 2,
            "CategoryName": "Condiments",
            "Description": "Sweet and savory sauces, relishes, spreads, and seasonings"
        },
        "FirstOrderedOn": new Date(1996, 8, 26)
    },
    {
        "ProductID": 4,
        "ProductName": "Chef Anton's Cajun Seasoning",
        "SupplierID": 2,
        "CategoryID": 2,
        "QuantityPerUnit": "48 - 6 oz jars",
        "UnitPrice": 22,
        "UnitsInStock": 53,
        "UnitsOnOrder": 0,
        "ReorderLevel": 0,
        "Discontinued": false,
        "Category": {
            "CategoryID": 2,
            "CategoryName": "Condiments",
            "Description": "Sweet and savory sauces, relishes, spreads, and seasonings"
        },
        "FirstOrderedOn": new Date(1996, 9, 19)
    },
    {
        "ProductID": 5,
        "ProductName": "Chef Anton's Gumbo Mix",
        "SupplierID": 2,
        "CategoryID": 2,
        "QuantityPerUnit": "36 boxes",
        "UnitPrice": 21.35,
        "UnitsInStock": 0,
        "UnitsOnOrder": 0,
        "ReorderLevel": 0,
        "Discontinued": true,
        "Category": {
            "CategoryID": 2,
            "CategoryName": "Condiments",
            "Description": "Sweet and savory sauces, relishes, spreads, and seasonings"
        },
        "FirstOrderedOn": new Date(1996, 7, 17)
    },
    {
        "ProductID": 6,
        "ProductName": "Grandma's Boysenberry Spread",
        "SupplierID": 3,
        "CategoryID": 2,
        "QuantityPerUnit": "12 - 8 oz jars",
        "UnitPrice": 25,
        "UnitsInStock": 120,
        "UnitsOnOrder": 0,
        "ReorderLevel": 25,
        "Discontinued": false,
        "Category": {
            "CategoryID": 2,
            "CategoryName": "Condiments",
            "Description": "Sweet and savory sauces, relishes, spreads, and seasonings"
        },
        "FirstOrderedOn": new Date(1996, 9, 19)
    },
    {
        "ProductID": 7,
        "ProductName": "Uncle Bob's Organic Dried Pears",
        "SupplierID": 3,
        "CategoryID": 7,
        "QuantityPerUnit": "12 - 1 lb pkgs.",
        "UnitPrice": 30,
        "UnitsInStock": 15,
        "UnitsOnOrder": 0,
        "ReorderLevel": 10,
        "Discontinued": false,
        "Category": {
            "CategoryID": 7,
            "CategoryName": "Produce",
            "Description": "Dried fruit and bean curd"
        },
        "FirstOrderedOn": new Date(1996, 7, 22)
    },
    {
        "ProductID": 8,
        "ProductName": "Northwoods Cranberry Sauce",
        "SupplierID": 3,
        "CategoryID": 2,
        "QuantityPerUnit": "12 - 12 oz jars",
        "UnitPrice": 40,
        "UnitsInStock": 6,
        "UnitsOnOrder": 0,
        "ReorderLevel": 0,
        "Discontinued": false,
        "Category": {
            "CategoryID": 2,
            "CategoryName": "Condiments",
            "Description": "Sweet and savory sauces, relishes, spreads, and seasonings"
        },
        "FirstOrderedOn": new Date(1996, 11, 1)
    },
    {
        "ProductID": 9,
        "ProductName": "Mishi Kobe Niku",
        "SupplierID": 4,
        "CategoryID": 6,
        "QuantityPerUnit": "18 - 500 g pkgs.",
        "UnitPrice": 97,
        "UnitsInStock": 29,
        "UnitsOnOrder": 0,
        "ReorderLevel": 0,
        "Discontinued": true,
        "Category": {
            "CategoryID": 6,
            "CategoryName": "Meat/Poultry",
            "Description": "Prepared meats"
        },
        "FirstOrderedOn": new Date(1997, 1, 21)
    },
    {
        "ProductID": 10,
        "ProductName": "Ikura",
        "SupplierID": 4,
        "CategoryID": 8,
        "QuantityPerUnit": "12 - 200 ml jars",
        "UnitPrice": 31,
        "UnitsInStock": 31,
        "UnitsOnOrder": 0,
        "ReorderLevel": 0,
        "Discontinued": false,
        "Category": {
            "CategoryID": 8,
            "CategoryName": "Seafood",
            "Description": "Seaweed and fish"
        },
        "FirstOrderedOn": new Date(1996, 8, 5)
    }
];

export { sampleProducts }
;

Custom Filter Cell

To render a custom filter cell in the Grid, use templates. To display a filter template in the header of the Grid columns, use any of the following approaches:

  • Using slots, as demonstrated by the filterSlotTemplate in the following example.
  • Using the render function, as demonstrated by the filterRender function in the following example.
  • Using Vue components, as demonstrated by the custom-numeric-filter component in the following example.
<div id="vueapp" class="vue-app">
    <Grid
      :data-items="products"
      :filterable="true"
      :filter="filter"
      @filterchange="filterChange"
      :columns="columns"
      :filter-cell-render="filterRender">
      <template v-slot:filterSlotTemplate="{props, methods}">
            <div>
              Filter Slot:
              <input type="text" :value="props.value" @input="(ev) => {methods.change({operator: 'contains', field: props.field, value: ev.target.value, syntheticEvent: ev});}">
              <button @click="(ev) => {methods.change({operator: '', field: '', value: '', syntheticEvent: ev});}">Clear</button>
              </div>
          </template>
     </Grid>
</div>
import Vue from 'vue';
import { Grid, GridToolbar, GridNoRecords } from '@progress/kendo-vue-grid';
import { filterBy, CompositeFilterDescriptor } from '@progress/kendo-data-query';
import { sampleProducts } from './app/products';

Vue.component('Grid', Grid);

var customnumeric = Vue.component('custom-numeric-filter', {
    template: `<div>
                <input ref='input' class='k-input' type='number' :value='value' @input='change' />
                <select ref='select' :value="operator" @change='change'>
                    <option value="eq" :selected="operator === null">Is Equal</option>
                    <option value="neq">Is Not Equal</option>
                </select>
                <button @click="reset">Clear</button>
            </div>`,
    props: {
        grid: Grid,
        field: String,
        filterType: String,
        value: [String, Number, Boolean, Date],
        operator: String
    },
    methods: {
        change (ev) {
            this.$emit('change', { operator: this.$refs.select.value, field: this.field, value: parseFloat(this.$refs.input.value), syntheticEvent: ev });
        },
        reset (ev) {
            this.$emit('change', { operator: '', field: '', value: '', syntheticEvent: ev });
        }
    }
})

new Vue({
    el: '#vueapp',
    data: function () {
        return {
            filter: {
                logic: "and",
                filters: [
                    { field: "UnitPrice", operator: "neq", value: 2 }
                ]
            },
            columns: [
                { field: 'ProductID', filterable:false, title: 'ID', width:'50px'},
                { field: 'ProductName', title: 'Product Name', filterCell: 'filterSlotTemplate'},
                { field: 'FirstOrderedOn', filter:'date', title: 'FirstOrderedOn'},
                { field: 'UnitPrice', filter:'numeric', title: 'UnitPrice', filterCell: customnumeric},
                { field: 'Discontinued', filter:'boolean', title: 'Discontinued'}
            ]
        };
    },
    computed: {
        products: function() {
            return filterBy(sampleProducts, this.filter);
        }
    },
    methods: {
        filterChange: function(ev) {
            this.filter = ev.filter;
        },
        filterRender: function(h, defaultRendering, props, change)        {
            return defaultRendering;
        }
    }
});
const sampleProducts = [
    {
        "ProductID": 1,
        "ProductName": "Chai",
        "SupplierID": 1,
        "CategoryID": 1,
        "QuantityPerUnit": "10 boxes x 20 bags",
        "UnitPrice": 18,
        "UnitsInStock": 39,
        "UnitsOnOrder": 0,
        "ReorderLevel": 10,
        "Discontinued": false,
        "Category": {
            "CategoryID": 1,
            "CategoryName": "Beverages",
            "Description": "Soft drinks, coffees, teas, beers, and ales"
        },
        "FirstOrderedOn": new Date(1996, 8, 20)
    },
    {
        "ProductID": 2,
        "ProductName": "Chang",
        "SupplierID": 1,
        "CategoryID": 1,
        "QuantityPerUnit": "24 - 12 oz bottles",
        "UnitPrice": 19,
        "UnitsInStock": 17,
        "UnitsOnOrder": 40,
        "ReorderLevel": 25,
        "Discontinued": false,
        "Category": {
            "CategoryID": 1,
            "CategoryName": "Beverages",
            "Description": "Soft drinks, coffees, teas, beers, and ales"
        },
        "FirstOrderedOn": new Date(1996, 7, 12)
    },
    {
        "ProductID": 3,
        "ProductName": "Aniseed Syrup",
        "SupplierID": 1,
        "CategoryID": 2,
        "QuantityPerUnit": "12 - 550 ml bottles",
        "UnitPrice": 10,
        "UnitsInStock": 13,
        "UnitsOnOrder": 70,
        "ReorderLevel": 25,
        "Discontinued": false,
        "Category": {
            "CategoryID": 2,
            "CategoryName": "Condiments",
            "Description": "Sweet and savory sauces, relishes, spreads, and seasonings"
        },
        "FirstOrderedOn": new Date(1996, 8, 26)
    },
    {
        "ProductID": 4,
        "ProductName": "Chef Anton's Cajun Seasoning",
        "SupplierID": 2,
        "CategoryID": 2,
        "QuantityPerUnit": "48 - 6 oz jars",
        "UnitPrice": 22,
        "UnitsInStock": 53,
        "UnitsOnOrder": 0,
        "ReorderLevel": 0,
        "Discontinued": false,
        "Category": {
            "CategoryID": 2,
            "CategoryName": "Condiments",
            "Description": "Sweet and savory sauces, relishes, spreads, and seasonings"
        },
        "FirstOrderedOn": new Date(1996, 9, 19)
    },
    {
        "ProductID": 5,
        "ProductName": "Chef Anton's Gumbo Mix",
        "SupplierID": 2,
        "CategoryID": 2,
        "QuantityPerUnit": "36 boxes",
        "UnitPrice": 21.35,
        "UnitsInStock": 0,
        "UnitsOnOrder": 0,
        "ReorderLevel": 0,
        "Discontinued": true,
        "Category": {
            "CategoryID": 2,
            "CategoryName": "Condiments",
            "Description": "Sweet and savory sauces, relishes, spreads, and seasonings"
        },
        "FirstOrderedOn": new Date(1996, 7, 17)
    },
    {
        "ProductID": 6,
        "ProductName": "Grandma's Boysenberry Spread",
        "SupplierID": 3,
        "CategoryID": 2,
        "QuantityPerUnit": "12 - 8 oz jars",
        "UnitPrice": 25,
        "UnitsInStock": 120,
        "UnitsOnOrder": 0,
        "ReorderLevel": 25,
        "Discontinued": false,
        "Category": {
            "CategoryID": 2,
            "CategoryName": "Condiments",
            "Description": "Sweet and savory sauces, relishes, spreads, and seasonings"
        },
        "FirstOrderedOn": new Date(1996, 9, 19)
    },
    {
        "ProductID": 7,
        "ProductName": "Uncle Bob's Organic Dried Pears",
        "SupplierID": 3,
        "CategoryID": 7,
        "QuantityPerUnit": "12 - 1 lb pkgs.",
        "UnitPrice": 30,
        "UnitsInStock": 15,
        "UnitsOnOrder": 0,
        "ReorderLevel": 10,
        "Discontinued": false,
        "Category": {
            "CategoryID": 7,
            "CategoryName": "Produce",
            "Description": "Dried fruit and bean curd"
        },
        "FirstOrderedOn": new Date(1996, 7, 22)
    },
    {
        "ProductID": 8,
        "ProductName": "Northwoods Cranberry Sauce",
        "SupplierID": 3,
        "CategoryID": 2,
        "QuantityPerUnit": "12 - 12 oz jars",
        "UnitPrice": 40,
        "UnitsInStock": 6,
        "UnitsOnOrder": 0,
        "ReorderLevel": 0,
        "Discontinued": false,
        "Category": {
            "CategoryID": 2,
            "CategoryName": "Condiments",
            "Description": "Sweet and savory sauces, relishes, spreads, and seasonings"
        },
        "FirstOrderedOn": new Date(1996, 11, 1)
    },
    {
        "ProductID": 9,
        "ProductName": "Mishi Kobe Niku",
        "SupplierID": 4,
        "CategoryID": 6,
        "QuantityPerUnit": "18 - 500 g pkgs.",
        "UnitPrice": 97,
        "UnitsInStock": 29,
        "UnitsOnOrder": 0,
        "ReorderLevel": 0,
        "Discontinued": true,
        "Category": {
            "CategoryID": 6,
            "CategoryName": "Meat/Poultry",
            "Description": "Prepared meats"
        },
        "FirstOrderedOn": new Date(1997, 1, 21)
    },
    {
        "ProductID": 10,
        "ProductName": "Ikura",
        "SupplierID": 4,
        "CategoryID": 8,
        "QuantityPerUnit": "12 - 200 ml jars",
        "UnitPrice": 31,
        "UnitsInStock": 31,
        "UnitsOnOrder": 0,
        "ReorderLevel": 0,
        "Discontinued": false,
        "Category": {
            "CategoryID": 8,
            "CategoryName": "Seafood",
            "Description": "Seaweed and fish"
        },
        "FirstOrderedOn": new Date(1996, 8, 5)
    }
];

export { sampleProducts }
;

In the above example the custom numeric filter could also be defined as a local component instance in the following way:

var customnumeric = {
    template: `<div>
                <input ref='input' class='k-input' type='number' :value='value' @input='change' />
                <select ref='select' :value="operator" @change='change'>
                    <option value="eq" :selected="operator === null">Is Equal</option>
                    <option value="neq">Is Not Equal</option>
                </select>
                <button @click="reset">Clear</button>
            </div>`,
    props: {
        grid: Grid,
        field: String,
        filterType: String,
        value: [String, Number, Boolean, Date],
        operator: String
    },
    methods: {
        change (ev) {
            this.$emit('change', { operator: this.$refs.select.value, field: this.field, value: parseFloat(this.$refs.input.value), syntheticEvent: ev });
        },
        reset (ev) {
            this.$emit('change', { operator: '', field: '', value: '', syntheticEvent: ev });
        }
    }
}

In this article