Multiple Independent Checkbox Lists in Grid

Hi,


In the grid component, I want to be able to provide independent lists for two checkbox lists that are use to filter the grid data.

Currently, if I set filter type to checkbox for a column and filter by one of these columns, the second filter will not work.

As far as I can tell this is because all of these filters use the same dataSource, which is supposed to be built on the server side from distinct values from the table relating to the the data.

In my scenario, I want to implement something like a custom drop down list, but using a multi-select checkbox list instead, this way I can provide the options and they can filter the data without affecting each other.

E.g I have one list



And another:


I want the lists used here never to change, to always show all the values that are available and not impact each other, which is currently not the case.

For example, a custom drop down list works using this code:

        get customerFilter(): any {
            let self = this;
            return {
                ui: {
                    create: (args) => {
                        let inputField = document.createElement('input', { className: 'flm-input' } as ElementCreationOptions);
                        args.target.appendChild(inputField);
                        self.dropdownInstance = new DropDownList({
                            dataSource: new DataManager(self.lookups.Customers),
                            fields: { text: 'companyName', value: 'id' },
                            placeholder: 'All',
                            popupHeight: '200px',
                            allowFiltering: true
                        } as any);
                        self.dropdownInstance.appendTo(inputField);
                    },
                    write: (args) => {
                        (self.dropdownInstance as DropDownList).value = args.filteredValue;
                    },
                    read: (args) => {
                        args.fltrObj.filterByColumn(args.column.field, args.operator, (self.dropdownInstance as DropDownList).value);
                    }
                }
            }
        }

Which gives me:



How can I change the component used here to be a checkbox list?

e.g



3 Replies 1 reply marked as answer

RR Rajapandi Ravi Syncfusion Team August 7, 2020 12:55 PM UTC

Hi Joshua, 

Greetings from syncfusion support 

Query#: How can I change the component used here to be a checkbox list? 

We have analyzed your query and we could see that you like to use the checkbox in dropdownlist. You can achieve your requirement by rendering the Multiselect component in filter menu and the MultiSelect has built-in support to select multiple values through checkbox, when mode property set as CheckBox. Please refer the below code example, sample and screenshot for more information. 

App.vue 
 
<template> 
  <div id="app"> 
    <ejs-grid 
      id="Grid" 
      :dataSource="data" 
      :allowPaging="true" 
      :allowFiltering="true" 
      :filterSettings="filterSettings" 
      ref="pgridtable" 
    > 
      <e-columns> 
        .  .  .  .  .  .  . 
        <e-column field="ShipCountry" :filter="filtercountry" headerText="Ship Country" width="150"></e-column> 
      </e-columns> 
    </ejs-grid> 
  </div> 
</template> 
 
<script> 
import Vue from "vue"; 
import { GridPlugin, Page, Filter } from "@syncfusion/ej2-vue-grids"; 
import { orderData } from "./dataSource"; 
import { MultiSelect, CheckBoxSelection } from "@syncfusion/ej2-dropdowns"; 
import { DataManager, DataUtil } from "@syncfusion/ej2-data"; 
import { createElement } from "@syncfusion/ej2-base"; 
import { MultiSelectPlugin } from "@syncfusion/ej2-vue-dropdowns"; 
MultiSelect.Inject(CheckBoxSelection); 
 
Vue.use(MultiSelectPlugin); 
Vue.use(GridPlugin); 
 
export default { 
  name: "App", 
  data() { 
    let dropInstance = null; 
    return { 
      data: orderData, 
      filterSettings: { type: "Menu" }, 
      filtercountry: { 
        ui: { 
          create: function(args) { 
            let db = new DataManager(orderData); 
            let flValInput = createElement("input", { className: "flm-input" }); 
            args.target.appendChild(flValInput); 
            dropInstance = new MultiSelect({ 
              dataSource: DataUtil.distinct(orderData, "ShipCountry"), 
              fields: { text: "ShipCountry", value: "Shipcountry" }, 
              placeholder: "Select a value", 
              popupHeight: "200px", 
              mode: "CheckBox" 
            }); 
            dropInstance.appendTo(flValInput); 
          }, 
          write: function(args) { 
            dropInstance.value = args.filteredValue; 
          }, 
          read: function(args) { 
            args.fltrObj.filterByColumn( 
              args.column.field, 
              "contains", 
             dropInstance.value 
            ); 
          } 
        } 
      } 
    }; 
  }, 
  methods: { 
     
  }, 
  provide: { 
    grid: [Page, Filter] 
  } 
}; 
</script> 
 
<style> 
</style> 
 


Screenshot: 

 

Regards, 
Rajapandi R 



JD Joshua Dunn August 11, 2020 02:55 PM UTC

Hi Rajapandi,

In the sample provided, if you select an item and then go to edit the filter again, you recieve this error:



So obivously this is not a complete solution.

I have managed to implement something that does not throw this error, but now I have encountered another difficulty.

When the value is updated, the predicate that is produced is not updated correctly.

E.g, I select Country A and filter. I then deselect Country A and select Country B. The predicate produced will still contain the first value, as well as the second.

Is there a way to "reset" this predicate between filtering operations, without quering again? 

I have actually achieved this functionality with the below code, but I wanted to know if there is a better  / more native way to do this.

The code for my custom filter looks like this:

        get checkboxFilter(): any {
            return {
                ui: {
                    create: (args) => {
                        let customFilter = this.customFilters.find(x => x.col == args.column.field);
                        args.getOptrInstance.dropOptr.element.parentElement.parentElement.style.display = "none";
                        let inputField = document.createElement('input', { className: 'flm-input' } as ElementCreationOptions);
                        args.target.appendChild(inputField);
                        let curVal = new Array<any>();
                        if (customFilter.instance.value != []) {
                            curVal = customFilter.instance.value;
                        }
                        customFilter.instance = new MultiSelect({
                            dataSource: new DataManager(customFilter.data),
                            enablePersistance: true,
                            fields: customFilter.fields,
                            placeholder: 'All',
                            popupHeight: '200px',
                            allowFiltering: true,
                            showSelectAll: true,
                            mode: 'CheckBox'
                        } as any);
                        customFilter.instance.value = curVal;
                        customFilter.instance.appendTo(inputField);
                    },
                    read: (args) => {
                        let customFilter = this.customFilters.find(x => x.col == args.column.field);
                        //Required to reset the predicate otherwise it contains previous filter value as well as new one
                        //Filters out stored filtering info for the column we are currently filtering
                        args.fltrObj.filterSettings.columns = args.fltrObj.filterSettings.columns.filter(x => x.field != args.column.field);
                        args.fltrObj.filterByColumn(args.column.field, "equal", customFilter.instance.value);
                    }
                }
            }
        }




Marked as answer

RR Rajapandi Ravi Syncfusion Team August 13, 2020 01:49 PM UTC

Hi Joshua, 

Thanks for the update 

We are happy to hear that you have resolved the issue at your end. 

And from validating your query we could seen that the way to you are removing the predicates was the best approach. And you can also achieve your requirement by using the below way. Please refer the below code example and sample for more information. 

 
read: function(args) { 
            args.fltrObj.filterSettings.columns = []; //it helps to clear the previous predicate values 
            args.fltrObj.filterByColumn( 
              args.column.field, 
              "equal", 
              dropInstance.value 
            ); 
          } 
 


Regards,
Rajapandi R 


Loader.
Up arrow icon