We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date

Filter array type columns

Hello, 

Is it possible to get the checkBox filter working with a column bound to an array ?

My data looks like this : 


let data = [
{
id: 1,
first_name: "The name",
tags: [{
id: "1",
name: "Renovation",
slug: "renovation"
},
{
id: "2",
name: "Chantier",
slug: "chantier"
}]
}
];
FYI, the grid is bound to a remote datasource using the URLAdaptor. 

Here is an example of how the tags are displayed in the grid : 


I would like to add a Checkbox filter that displays all available tags individually. A row should be displayed if it contains one or more tags.
Could you please provide an example for this ? 

Best regards, 
Yohan

4 Replies

TS Thavasianand Sankaranarayanan Syncfusion Team October 23, 2019 01:34 PM UTC

Hi Yohan, 
 
Greetings from Syncfusion support. 
 
By default Essential JavaScript 2 Grid supports only one to one filtering and the one to many filtering will not work. However you can achieve this requirement by customizing the default checkbox filter dialog dataSource and DataUtil functions for the filtering actions. 
 
This is demonstrated in the below sample code where we have provided custom dataSource inside the “actionBegin” event and overridden the DataUtil function for filtering action, 
 
// Grid’s data source 
this.gridData = [ 
    { 
      id: 1, name: 'Kia Silverbrook', Work: [{ 
        Tasks: "Labelling" 
      }] 
    }, 
    { 
      id: 2, name: 'Simon R. Walmsley', Work: [{ 
        Tasks: "Reviewing", 
      }, 
      { 
        Tasks: "Allocating" 
      }] 
    }, 
    { 
      id: 3, name: 'Paul Lapstun', Work: [{ 
        Tasks: "Labelling", 
      }, 
      { 
        Tasks: "Allocating" 
      }] 
    }, 
    { 
      id: 4, name: 'Akira Nakazawa', Work: [{ 
        Tasks: "Reviewing", 
      }] 
    }, 
    { 
      id: 5, name: 'Gregory McAvoy', Work: [{ 
        Tasks: "Marketing", 
      }], 
    }, 
  ] 
 
  // Overriding DataUtil equal method 
  DataUtil.fnOperators.equal = function (actual, expected, ignoreCase, ignoreAccent) { 
    if (Array.isArray(actual)) { 
      if (expected == "") { 
        return !actual.length; 
      } 
 
      return JSON.stringify(actual).includes(expected) 
    } else { 
      if (ignoreAccent) { 
        actual = DataUtil.ignoreDiacritics(actual); 
        expected = DataUtil.ignoreDiacritics(expected); 
      } 
      if (ignoreCase) { 
        return DataUtil.toLowerCase(actual) === DataUtil.toLowerCase(expected); 
      } 
      return actual === expected; 
    } 
  }; 
 
  // Overriding DataUtil notequal method 
  DataUtil.fnOperators.notequal = function (actual, expected, ignoreCase, ignoreAccent) { 
    if (Array.isArray(actual)) { 
      if (expected == "") { 
        return actual.length; 
      } 
      return !JSON.stringify(actual).includes(expected) 
    } else { 
      if (ignoreAccent) { 
        actual = DataUtil.ignoreDiacritics(actual); 
        expected = DataUtil.ignoreDiacritics(expected); 
      } 
      return !DataUtil.fnOperators.equal(actual, expected, ignoreCase); 
    } 
  }; 
 
  // Grid’s actionBegin event function 
  actionBegin(args) { 
    if (args.requestType === 'filterbeforeopen' && args.columnName === 'Work') { 
      // Modifying filter datasource 
      args.filterModel.options.dataSource = this.getDataSource(); 
    } 
 
    getDataSource() { 
      var data = []; 
      var flag = true; 
      var lookup = {}; 
      var Work = this.gridData.map(value => value.Work); 
 
      Work.forEach((arr) => { 
        arr.forEach((task) => { 
          if (!(task.Tasks in lookup)) { 
            data.push({ Work: task.Tasks }); 
            lookup[task.Tasks] = true 
          } 
        }) 
        if (!arr.length && flag) { 
          data.push({}) 
          flag = false; 
        } 
      }) 
      return data; 
    } 
 
We have prepared a sample based on this for your reference. You can find it below, 
 
 
Regards, 
Thavasianand S. 



YD Yohan D October 25, 2019 07:52 AM UTC

Thank you for your quick et accurate answer !

This example works great with local data but not with remote data. 
Furthermore, datasource is an array of objects, and I would like to display the label and use the slug column for filtering.


To summarize: 

- How can I customize the request that is sent to the server so it looks like this: 

{
"requiresCounts": true,
"where": [
{
"isComplex": true,
"ignoreAccent": false,
"condition": "and",
"predicates": [
{
"isComplex": true,
"ignoreAccent": false,
"condition": "or",
"predicates": [
{
"isComplex": false,
"field": "tags__slug",
"operator": "in",
"value": ["jambon"],
"ignoreCase": true,
"ignoreAccent": false
},
{
"isComplex": false,
"field": "tags__slug",
"operator": "in",
"value": ["test"],
"ignoreCase": true,
"ignoreAccent": false
}
]
}
]
}
],
"sorted": [
{
"name": "created_at",
"direction": "descending"
}
],
"params": {
"filter": {}
},
"filter": {},
"skip": 0,
"take": 12
}

I have seen that it is possible to override some functions like createFilterItems or filterBtnHandler from CheckboxFilter to override the operator and the value sent as list but I don't know it this is the correct way to do it.


TS Thavasianand Sankaranarayanan Syncfusion Team October 31, 2019 08:51 AM UTC

Hi Yohan, 
 
We are validating for your requirement (Customized filtering option in server end) which we achieved in the client end. Once we complete the validation then we will provide the further detail on this. 
 
Regards, 
Thavasianand S. 



TS Thavasianand Sankaranarayanan Syncfusion Team November 4, 2019 11:00 AM UTC

Hi Yohan, 

We validated your requirement – “Customized filtering option in server end” from our side. Since you have bound multiple values in a single column, for displaying them as single values you would need to filter them in the server side when the filtering operation is called. But on checking this scenario there were a lot of complexities like splitting the multiple values in the columns and assign them to a single list and then send the list back to client, on filtering checking the split values and comparing them with the multiple values in the column and then sending back the result, filtering other columns case must perform properly with the multiple column values. 

Due to these complex cases we suggest you to use the multiple column values separately as different columns and this can be displayed in the grid as a single column using the valueAccessor property. On using this way we can compare the values of both columns in the server side and return the filtering list back to the client. Can you please tell us if this way would be feasible for you to use, if so we can proceed further in this method. Also can you please confirm whether you have using list binding or datatable or sqiserver for data binding in Grid. 
 
Regards, 
Thavasianand S. 


Loader.
Live Chat Icon For mobile
Up arrow icon