How to combine Filtering, Grouping, and Sorting in Kendo UI Vue Grid (native)

2.8k Views Asked by At

I'm trying to enable some operations on my grid such as grouping, filtering and sorting, individually they works as shown in the docs but there is no an example of those functionality working together.

By myself I was able to combine sorting and filtering but grouping does not work when i'm adding it as it shown in the docs. look at at my code

<template>
  <div>
    <Grid :style="{height: '100%'}"
        ref="grid"
        :data-items="getData"
        :resizable="true"
        :reorderable="true"
        @columnreorder="columnReorder"
        :filterable="true"
        :filter="filter"
        @filterchange="filterChange"
        :sortable="true"
        :sort= "sort"
        @sortchange="sortChangeHandler"
        :groupable="true"
        :group= "group"
        @dataStateChange="dataStateChange"
        :columns="columns">
    </Grid>
  </div>
</template>
<script>
  export default {
    data() {
      return {
        items: [],
        editID: null,
        columns: [
         { field: 'AbsenceEmployeID', filterable:false, editable: false, title: '#'},
         { field: 'Employe', title: 'Employer', cell: DropDownEmployes},
         { field: 'Remarque', title: 'Remarque'},
         { field: 'Type', title: 'Type', cell: DropDownTypes},
         { field: 'CreatedDate', filter:'date', editable: false, editor: 'date', title: 'créé le', format: '{0:d}'},
         { title: 'Actions', filterable:false, cell: CommandCell}
        ],
        filter: {
          logic: "and",
          filters: []
        },
        sort: [
          { field: 'CreatedDate', dir: 'desc' }
        ],
        group: [],
        gridData: []
      }
    }
    mounted() { 
      this.loadItems()
    },
    computed: {
      absencesList() {
        return this.items.map((item) => Object.assign({ inEdit: item.AbsenceEmployeID === this.editID}, item));
     },
     getData() {
       return orderBy(filterBy(this.absencesList, this.filter), this.sort);
     },
     ...mapState({
       absences: state => state.absences.absences
      })
    }
    methods: {
      loadItems () {
        this.$store.dispatch('absences/getAbsences')
          .then(resp => {
            this.items = this.absences.map(item => item)
          })
      },
      filterChange: function(ev) {
       this.filter = ev.filter;
      },
      columnReorder: function(options) {
        this.columns = options.columns;
      },
      sortChangeHandler: function(e) {
        this.sort = e.sort;
      },

      // the following is for grouping but not yet used, read more
      groupedData: function () {
        this.gridData = process(this.getData, {group: this.group});
      },
      createAppState: function(dataState) {
        this.group = dataState.group;
        this.groupedData();
      },
      dataStateChange: function (event) {
        this.createAppState(event.data);
      },
    }
  }
</script>

The last three methods are not used yet, so filtering and sorting is working perfectly as of now. then in other to enable grouping I want to replace :data-items="getData" by :data-items="gridData" and run this.groupedData() method after the items are loaded but grouping doesn't work. I think everything should be handle by the dataStateChange event and process() function but I also tried but without success

2

There are 2 best solutions below

7
Plamen Zdravkov On

If you define the filterchange and sortchange events they are being triggered for filter and sort and you will have to updated data in their handlers. If you rather want to use datastatechage event for all the changes you have to remove the filterchange and sortchange events and the datastatechage event will be triggered instead of them. In this case you will have to update the data in its handler.

You can use the process method of @progress/kendo-data-query by passing the respective parameter each data change that is needed as in the example below:

const result = process(data, {
    skip: 10,
    take: 20,
    group: [{
      field: 'category.categoryName',
            aggregates: [
                  { aggregate: "sum", field: "unitPrice" },
                  { aggregate: "sum", field: "unitsInStock" }
            ]
      }],
    sort: [{ field: 'productName', dir: 'desc' }],
    filter: {
        logic: "or",
        filters: [
          { field: "discontinued", operator: "eq", value: true },
          { field: "unitPrice", operator: "lt", value: 22 }
        ]
    }
});

Hers is a sample stackblitz example where such example is working correctly - https://stackblitz.com/edit/3ssy1k?file=index.html

0
H.Azizkhani On

You need to implement the groupchange method to handle Grouping

I prefer to use process from @progress/kendo-data-query

The following is a complete example of this

<template>
<Grid :style="{height: height}"
      :data-items="gridData"
      :skip="skip"
      :take="take"
      :total="total"
      :pageable="pageable"
      :page-size="pageSize"
      :filterable="true"
      :filter="filter"
      :groupable="true"
      :group="group"
      :sortable="true"
      :sort="sort"
      :columns="columns"
      @sortchange="sortChangeHandler"
      @pagechange="pageChangeHandler"
      @filterchange="filterChangeHandler"
      @groupchange="groupChangeHandler"
/>
</template>

<script>
import '@progress/kendo-theme-default/dist/all.css';
import { Grid } from '@progress/kendo-vue-grid';
import { process } from '@progress/kendo-data-query';

const sampleProducts = [
{
    'ProductID': 1,
    'ProductName': 'Chai',
    'UnitPrice': 18,
    'Discontinued': false,
},
{
    'ProductID': 2,
    'ProductName': 'Chang',
    'UnitPrice': 19,
    'Discontinued': false,
},
{
    'ProductID': 3,
    'ProductName': 'Aniseed Syrup',
    'UnitPrice': 10,
    'Discontinued': false,
},
{
    'ProductID': 4,
    'ProductName': "Chef Anton's Cajun Seasoning",
    'UnitPrice': 22,
    'Discontinued': false,
},
];

export default {
components: {
    Grid,
},
data () {
    return {
        gridData: sampleProducts,
        filter: {
            logic: 'and',
            filters: [],
        },
        skip: 0,
        take: 10,
        pageSize: 5,
        pageable: {
            buttonCount: 5,
            info: true,
            type: 'numeric',
            pageSizes: true,
            previousNext: true,
        },
        sort: [],
        group: [],
        columns: [
            { field: 'ProductID', filterable: false, title: 'Product ID', width: '130px' },
            { field: 'ProductName', title: 'Product Name' },
            { field: 'UnitPrice', filter: 'numeric', title: 'Unit Price' },
            { field: 'Discontinued', filter: 'boolean', title: 'Discontinued' },
        ],
    };
},
computed: {
    total () {
        return this.gridData ? this.gridData.length : 0;
    },
},
mounted () {
    this.getData();
},
methods: {
    getData: function () {
        this.gridData = process(sampleProducts,
            {
                skip: this.skip,
                take: this.take,
                group: this.group,
                sort: this.sort,
                filter: this.filter,
            });
    },
    // ------------------Sorting------------------
    sortChangeHandler: function (event) {
        this.sort = event.sort;
        this.getData();
    },
    // ------------------Paging------------------
    pageChangeHandler: function (event) {
        this.skip = event.page.skip;
        this.take = event.page.take;
        this.getData();
    },
    // ------------------Filter------------------
    filterChangeHandler: function (event) {
        this.filter = event.filter;
        this.getData();
    },
    // ------------------Grouping------------------
    groupChangeHandler: function (event) {
        this.group = event.group;
        this.getData();
    },
},
};
</script>