Question

I'm trying to put 2 filters on kendo grid with 'OR' logic. It's not working. I need the grid to be filtered with the both the dropdowns. If in Foo dropdown 'foo1' is selected and in Bar dropdown 'All' selected, then the grid should be displaying

 foo     bar
  1       1
  1       2

Code below:

$(function() {  
 var grid=$("#grid").kendoGrid({
 dataSource: {
 data: [
    { foo: "1", bar: "1" },{ foo: "1", bar: "2" },
    { foo: "2", bar: "2" },{ foo: "2", bar: "1" },
    { foo: "3", bar: "3" },{ foo: "3", bar: "2" }
    ]
},
columns: [
  "foo","bar"
],
toolbar: kendo.template($("#template").html())
});
grid.find("#foo").kendoDropDownList({
        dataTextField: "name",
        dataValueField: "id",
        autoBind: false,
        optionLabel: "All",
dataSource: [{id:'1', name:'foo1'}, {id:'2', name:'foo2'},{id:'3', name:'foo3'}],
        change: function () {
          var ds = $("#grid").data("kendoGrid").dataSource;        

var filter = {
  logic: "and",
  filters: []
};    
if (this.value()) {
filter.filters.push([{ field: "bar", operator: "eq", value:      
$("#bar").data('kendoDropDownList').value() },
 { field: "foo", operator: "eq", value:  $("#foo").data('kendoDropDownList').value() } 
]);
}
          ds.filter([filter]);
 }
});
grid.find("#bar").kendoDropDownList({
        dataTextField: "name",
        dataValueField: "id",
        autoBind: false,
        optionLabel: "All",
dataSource: [{id:'1', name:'bar1'}, {id:'2', name:'bar2'},{id:'3', name:'bar3'}],
        change: function () {
          var ds = $("#grid").data("kendoGrid").dataSource;        

var filter = {
  logic: "and",
  filters: []
};    
if (this.value()) {
filter.filters.push([{ field: "bar", operator: "eq", value:    
$("#bar").data('kendoDropDownList').value() },
 { field: "foo", operator: "eq", value:  $("#foo").data('kendoDropDownList').value() } 
]);
}
          ds.filter([filter]);
}
});
});
After pushing the filters to the filter array the grid datasource is not filtered.

Updated jsbin below: http://jsbin.com/izuloj/23/edit

Was it helpful?

Solution

There are couple of problems:

  • The argument for DataSource filters is an array but you are pushing an array when you do:
filter.filters.push([
    { field: "bar", operator: "eq", value:  $("#bar").data('kendoDropDownList').value() },
    { field: "foo", operator: "eq", value:  $("#foo").data('kendoDropDownList').value() } 
]);
  • Comparing with empty is not the same that not adding the condition. So you should actually do:
// If there is some value in "bar" we add a condition for filtering it
if ($("#bar").data('kendoDropDownList').value()) {
    filter.filters.push({ 
        field: "bar", 
        operator: "eq", 
        value:  $("#bar").data('kendoDropDownList').value() }
    );
}

// If there is some value in "foo" we add a condition for filtering it
if ($("#foo").data('kendoDropDownList').value()) {
    filter.filters.push(
        { 
            field: "foo", 
            operator: "eq", 
            value:  $("#foo").data('kendoDropDownList').value() } 
    );
}
  • Finally, you should not set any filter if both drop down inputs are empty but in that case you cannot send an empty filter array, you should do ds.filter({})) instead.

So your change function ends being:

function onChange () {
    var ds = $("#grid").data("kendoGrid").dataSource;        
    var filtering = false;

    var filter = {
        logic: "and",
        filters: []
    };    
    if ($("#bar").data('kendoDropDownList').value()) {
        filtering = true;
        filter.filters.push(
            { field: "bar", operator: "eq", value:  $("#bar").data('kendoDropDownList').value() }
        );
    }
    if ($("#foo").data('kendoDropDownList').value()) {
        filtering = true;
        filter.filters.push(
            { field: "foo", operator: "eq", value:  $("#foo").data('kendoDropDownList').value() } 
        );
    }
    if (filtering) {
        ds.filter([filter]);
    } else {
        ds.filter({});
    }
}

Your code modified here : http://jsbin.com/izuloj/31/edit

OTHER TIPS

Instead of

var filter = {
  logic: "and",
  filters: []
};    
if (this.value()) {
filter.filters.push([{ field: "bar", operator: "eq", value:    
$("#bar").data('kendoDropDownList').value() },
 { field: "foo", operator: "eq", value:  $("#foo").data('kendoDropDownList').value() } 
]);
}
          ds.filter([filter]);

Doing below works....easy to read

     if ( $("#foo").data('kendoDropDownList').value() === "")
          {
            ds.filter( { field: "bar", operator: "eq", value: $("#bar").data('kendoDropDownList').value()});
          }
          else
          {

          ds.filter({
                  logic: "and",
                  filters: [{ field: "foo", operator: "eq", value: $("#foo").data('kendoDropDownList').value() },{ field: "bar", operator: "eq", value: $("#bar").data('kendoDropDownList').value()  }]
          });
          }

Remove the square brackets on ds.filter([filter]); so that it becomes ds.filter(filter);.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top