问题
I have a grid containing three multiselect controls in the toolbar which are to be used to filter the grid datasource based on selections made.
At the moment, I have the below function, fired during a change
event in any of the multiselect controls. This function accepts values
containing the selected items in the multiselect control changed and filterID
which is the field
name to be used during the filtering.
function applyClientFilters(values, filterID) {
var grid = $("#grid").data("kendoGrid");
var gridDataSource = grid.dataSource;
var filter = gridDataSource.filter();
// does the selected drop down contain a value
// if yes, then apply this filter to the necessary drop down
// otherwise remove the filter
if (values.length > 0) {
// has a filter been setup yet on the datasource?
if (filter && filter.filters.length > 0) {
// firstly check to see if filter has already been applied and if so remove
for (var i = 0; i < filter.filters.length; ++i) {
// check to see if filter field already exists i.e. analyte has already been filtered
// and check to see if the value at this field already exists as a filtered item
if (filter.filters[i].field === filterID && values.indexOf(filter.filters[i].value) > -1) {
filter.filters.splice(i, 1);
}
}
// apply new filter(s)
for (var i = 0; i < values.length; ++i) {
filter.filters.push({ field: filterID, operator: "eq", value: parseInt(values[i]) });
}
gridDataSource.query({
filter: filter,
pageSize: 10,
page: 1,
group: [{
field: "InstrumentName",
dir: "asc"
}, {
field: "AnalyteName",
dir: "asc"
}, {
field: "MethodName",
dir: "asc"
}]
});
}
else {
// apply new filter
gridDataSource.filter({
logic: "or",
filters: [
{
field: filterID,
operator: "eq",
value: parseInt(values),
}
]
});
}
} else {
if (filter && filter.filters.length > 0) {
// remove existing filter
for (var i = 0; i < filter.filters.length; ++i) {
if (filter.filters[i].field === filterID) {
filter.filters.splice(i, 1);
}
}
gridDataSource.query({
filter: filter,
pageSize: 10,
page: 1,
group: [{
field: "InstrumentName",
dir: "asc"
}, {
field: "AnalyteName",
dir: "asc"
}, {
field: "MethodName",
dir: "asc"
}]
});
}
}
}
Using only the or
logic when filtering is fine with an individual multiselect selection i.e. selecting multiple methods will filter them as expected. However, the logic needs to be and
when used across different multiselect controls.
Example
- Select 'Analyte A' -> filters grid datasource to only display 'Analyte A'
- Select 'Method A' -> filters grid datasource to display 'Analyte A' and 'Method A'
- Select 'Method B' -> filters grid datasource to display 'Analyte A' and 'Method A' or 'Method B'
Is it possible to combine filter logic operators with Kendo datasource filtering to achieve the above scenario?
回答1:
I came up a solution which simplifies the filtering substantially. Instead of adding/removing/updating filters, I clear the datasource filter during the change
event of any of the multiselect components, determine which filters are to be applied based on the selected item(s) in each multiselect and build a filter object based on the selections, like so:
function applyClientFilters() {
var grid = $("#reportGrid").data("kendoGrid");
var gridDataSource = grid.dataSource;
// clear existing datasource
gridDataSource.filter([]);
// extract selected items from each of the three multiselect controls
var selectedAnalytes = $("#analyte").data("kendoMultiSelect").value();
var selectedMethods = $("#method").data("kendoMultiSelect").value();
var selectedInstruments = $("#instrument").data("kendoMultiSelect").value();
// setup filter object (using and logic)
var filter = {
logic: "and",
filters: [] // ready for filter from each of the three multiselect controls
};
// loop over each of the three extracted selected items variables
// push new filter into array of filters with or logic on each filter
if (selectedAnalytes.length > 0) {
var analyteFilter = {
logic: "or",
filters: [] // ready for filter for each of the selected analytes
};
for (var i = 0; i < selectedAnalytes.length; ++i) {
analyteFilter.filters.push( { field: "AnalyteID", operator: "eq", value: parseInt(selectedAnalytes[i]) } )
}
filter.filters.push(analyteFilter);
}
if (selectedMethods.length > 0) {
var methodFilter = {
logic: "or",
filters: [] // ready for filter for each of the selected methods
};
for (var i = 0; i < selectedMethods.length; ++i) {
methodFilter.filters.push({ field: "MethodID", operator: "eq", value: parseInt(selectedMethods[i]) })
}
filter.filters.push(methodFilter);
}
if (selectedInstruments.length > 0) {
var instrumentFilter = {
logic: "or",
filters: [] // ready for filter for each of the selected instruments
};
for (var i = 0; i < selectedInstruments.length; ++i) {
instrumentFilter.filters.push({ field: "InstrumentID", operator: "eq", value: parseInt(selectedInstruments[i]) })
}
filter.filters.push(instrumentFilter);
}
// apply filter query to datasource
gridDataSource.query({
filter: filter,
pageSize: 10,
page: 1,
group: [{
field: "InstrumentName",
dir: "asc"
}, {
field: "AnalyteName",
dir: "asc"
}, {
field: "MethodName",
dir: "asc"
}]
});
}
来源:https://stackoverflow.com/questions/43780495/custom-filtering-with-multi-select-drop-downs