This is a migrated thread and some comments may be shown as answers.

How to combine these two filter objects?

9 Answers 728 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Carey
Top achievements
Rank 1
Carey asked on 26 Aug 2014, 11:40 PM
I've got a custom dropdown multi-select widget in one of my grid column headers, "Status". Each of the three statuses that can be chosen represent a group of statuses to show together when one of the dropdown values is selected. I need to be sure not to wipe out any current statuses that might be applied to my grid from the other columns. 

For example, I retrieve the current filters like so:

var grid = $('#accountsGrid');
var currentFilters = grid.data('kendoGrid').dataSource.filter();

Which gives me this object:
{"filters":[{"field":"name","operator":"contains","value":"JOHNSON"},{"field":"city","operator":"contains","value":"MILWAUKEE"},{"field":"state","operator":"eq","value":"WI"}],"logic":"and"}

I then build my status filter, resulting in this object:
{"logic":"or","filters":[{"field":"status","operator":"eq","value":"A"},{"field":"status","operator":"eq","value":"G"},{"field":"status","operator":"eq","value":"O"},{"field":"status","operator":"eq","value":"P"},{"field":"status","operator":"eq","value":"S"}]}

I then combine them together and apply to the datasource:

var newFilters = { logic: "and", filters: [] };
newFilters.filters.push(currentFilters);
newFilters.filters.push(statusFilters);
grid.data('kendoGrid').dataSource.filter(newFilters);

newFilters object:
{"logic":"and","filters":[{"filters":[{"field":"name","operator":"contains","value":"JOHNSON"},{"field":"city","operator":"contains","value":"MILWAUKEE"}],"logic":"and"},{"logic":"or","filters":[{"field":"status","operator":"eq","value":"A"},{"field":"status","operator":"eq","value":"G"},{"field":"status","operator":"eq","value":"O"},{"field":"status","operator":"eq","value":"P"},{"field":"status","operator":"eq","value":"S"}]}]

Here's my issue: when status gets changed again, I need to get the current filters (which will be the above value), but I need to parse out any existing status filters, so I can rebuild with the new criteria, without losing any other filter information. I think it's the nested result from combining filters that's making it so difficult, but I also think someone with experience transversing these kind of objects would probably be able to do it in their sleep!





9 Answers, 1 is accepted

Sort by
0
Carey
Top achievements
Rank 1
answered on 26 Aug 2014, 11:41 PM
Oops, sorry for the misleading thread name...when I first started this post, I was having issues with the combining of objects!
0
Accepted
Daniel
Telerik team
answered on 28 Aug 2014, 01:48 PM
Hello,

You can use the following logic(used by the filter menu) to remove the filters for a field and preserve the other filters:
function removeFiltersForField(expression, field) {
    if (expression.filters) {
        expression.filters = $.grep(expression.filters, function(filter) {
            removeFiltersForField(filter, field);
            if (filter.filters) {
                return filter.filters.length;
            } else {
                return filter.field != field;
            }
        });
    }
}
var filter = that.dataSource.filter() || { filters:[], logic: "and" };
 
removeFiltersForField(filter, "status");

I created an example that demonstrates this approach.


Regards,
Daniel
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
0
Carey
Top achievements
Rank 1
answered on 28 Aug 2014, 04:20 PM
Exactly what I was looking for! Thanks, Daniel.
0
Carey
Top achievements
Rank 1
answered on 29 Aug 2014, 10:09 PM
Daniel,

I was hoping you could help with another issue on a similar subject, that is with my kendoMultiSelectBox in my column header of a grid. Everything works great now that I'm manually manipulating the filter object when checkbox selections are made. However, I disabled sorting on this column due to the sort event firing every time the dropdown was opened, which makes sense because my dropdown element is getting created within the "k-link" anchor tag that wraps the column header waiting for a click to fire sorting. Now, the users want sorting AND the dropdown and I'm trying to figure out a way for them to have their cake and eat it too!

First, here's my column definition:
{
    field: 'status',
    title: 'Status',
    width: 130,
    filterable: false,
    sortable: false,
    headerTemplate: '<input id="statusMultiSelect" style="width:90px" />',
    template: function(dataItem) {
        return dataItem.statusDesc;
    }
},

Here's my widget:
var statusDropdown = $('#statusMultiSelect');
statusDropdown.kendoMultiSelectBox({
    dataTextField: 'text',
    dataValueField: 'value',
    dataSource: [{"value":"AC","text":"Active"},{"value":"OH","text":"On Hold"},{"value":"CL","text":"Closed"}],
    showSelectAll: true,
    //autoBind: false,
    emptySelectionLabel: "Status",
    selectionChanged: function() {
    applyStatusFilter(this.value());
    }
});

Is there a way I can enable filtering, yet keep it from firing when clicking within my dropdown box? I've already set my column width a little bigger than my widget, so there's room for a user to click inside the column header box without being in the dropdown. I was hoping somehow I could make this the only area that would fire the sort event.
0
Accepted
Daniel
Telerik team
answered on 02 Sep 2014, 10:54 AM
Hi again,

I can suggest either to move the multiselectbox to the toolbar or to stop the click event propagation in order to prevent sorting when clicking on the widget e.g.
var statusDropdown = $('#statusMultiSelect');
statusDropdown.kendoMultiSelectBox({
   ...
});
statusDropdown.data("kendoMultiSelectBox").wrapper.on("click", function (e) {
    e.stopPropagation();
});


Regards,
Daniel
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
0
Carey
Top achievements
Rank 1
answered on 02 Sep 2014, 03:55 PM
Thanks Daniel...I used the stop propagation angle and it worked fine. One odd thing I just noticed is that when I change the column setting to "sortable: true", it causes the down arrow in my dropdown to disappear. It looks like I lose the class on the second span on the right hand-side of the dropdown that displays the down arrow, but as soon as I disable sorting it comes back. Is there an issue with displaying down arrows both in the dropdown and in the column (when it's clicked to enable sorting)?
0
Carey
Top achievements
Rank 1
answered on 02 Sep 2014, 09:03 PM
I tried the following JQuery command after the dropdown is created:

$("span.k-select").html('<span class="k-icon k-i-arrow-s"></span>');

But my newly rendered down arrow only appears for a flicker. I suspect that when sorting is enabled, it's removing all arrow related classes from all spans within my header, so it can then decide if it should display up, down, or none. 

Here's the generated HTML when column sorting is disabled:

<th class="k-header" data-title="Status" data-field="status" role="columnheader">
  <span class="k-widget k-dropdown k-header" style="width: 90px;" unselectable="on" role="listbox" aria-haspopup="true" aria-expanded="false" tabindex="0" aria-owns="statusMultiSelect_listbox" aria-disabled="false" aria-readonly="false" aria-busy="false">
    <span class="k-dropdown-wrap k-state-default custom-multiselect-summary-empty" unselectable="on">
      <span class="k-input" unselectable="on">Status</span>
      <span class="k-select" unselectable="on">
        <span class="k-icon k-i-arrow-s"></span>
      </span>
    </span>
    <input id="statusMultiSelect" style="width: 90px; display: none;" data-role="multiselectbox">
  </span>
</th>

And here's the HTML with sorting enabled and activated in my column:

<th class="k-header" data-title="Status" data-field="status" role="columnheader" data-role="sortable" style="background-color: rgb(211, 211, 211);" data-dir="desc" aria-sort="descending">
  <a class="k-link" href="#">
    <span class="k-widget k-dropdown k-header" style="width: 90px;" unselectable="on" role="listbox" aria-haspopup="true" aria-expanded="false" tabindex="0" aria-owns="statusMultiSelect_listbox" aria-disabled="false" aria-readonly="false" aria-busy="false">
      <span class="k-dropdown-wrap k-state-default custom-multiselect-summary-empty" unselectable="on">
        <span class="k-input" unselectable="on">Status</span>
        <span class="k-select" unselectable="on"></span>
      </span>
      <input id="statusMultiSelect" style="width: 90px; display: none;" data-role="multiselectbox">
    </span>
    <span class="k-icon k-i-arrow-s"></span>
  </a>
</th>


0
Daniel
Telerik team
answered on 04 Sep 2014, 12:55 PM
Hi,

Indeed, since the same class is used to display the sort direction on the header, the arrow will be removed. The approach with adding the element after the initialization will not work because it will be removed again after the data is bound. You will need to use the dataSource change event in order to add the element again e.g.
var statusDropdown = $('#statusMultiSelect');
statusDropdown.kendoMultiSelectBox({
    ...
});
 
var grid = $('#accountsGrid').data("kendoGrid");
grid.dataSource.bind("change", function () {
    statusDropdown.data("kendoMultiSelectBox").wrapper.find("span.k-select").html('<span class="k-icon k-i-arrow-s"></span>');
});


Regards,
Daniel
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
0
Carey
Top achievements
Rank 1
answered on 04 Sep 2014, 02:14 PM
Thanks again, Daniel. I actually just chose to add my own icon to the dropdown, to help differentiate between the dropdown and the sorting arrow:

$("span.k-select").html('<span id="dropDownArrow"></span>');
#dropDownArrow {
    background:url(/images/module/home/down_arrow-16.png);
    background-repeat: no-repeat;
    margin-top:5px;
    height:16px;
    display: block;
}

Tags
Grid
Asked by
Carey
Top achievements
Rank 1
Answers by
Carey
Top achievements
Rank 1
Daniel
Telerik team
Share this question
or