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

Multi Filter checkbox for Dropdown

7 Answers 473 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Barry
Top achievements
Rank 1
Barry asked on 23 Jul 2015, 09:31 AM

 

I have a grid in which one of the columns is a dropdown. I'd like to enable the Multi Filter checkboxes for this column.

How can I do this?  If I set Multi to true it just displays the usual dropdown filter menu.

 

7 Answers, 1 is accepted

Sort by
0
Barry
Top achievements
Rank 1
answered on 23 Jul 2015, 09:38 AM

Apologies - please delete this post.

 

0
Barry
Top achievements
Rank 1
answered on 23 Jul 2015, 09:46 AM

Ok I am not actually this crazy normally... I thought I had got this working but that is not the case. 

The Multi Filter Checkboxes now appear for the dropdown columns however, they contain ALL possible dropdown values and not just the values that are in the grid. 

Is there anyway to restrict this so that it behaves like the other multi filter checkboxes?

0
Georgi Krustev
Telerik team
answered on 27 Jul 2015, 08:28 AM
Hello Barry,

In general, you will need to enable the "Multi" option, telling the grid to use MultiCheck widget as a filter menu for the particular column. You can see this in our online "Filter multi checkboxes" demo:
In general, the MultiCheck widget will filter the items internally in order to display distinct ones. If you are using a remote binding, then you will need to return the unique values manually. Please refer to the "Filter_Multi_CheckboxesController.cs" file, in the aforementioned online demo.

Regards,
Georgi Krustev
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Barry
Top achievements
Rank 1
answered on 27 Jul 2015, 09:07 AM

Hi Georgi,

I am using remote binding, however I need the Filter Checkboxes datasource to be re-bound any time the grid is filtered. To complicate matters further, I have pagination enabled on the grid. So I need the filter menus to use distinct values from the entire dataset, not just page 1, and to also take in to account any filtering already applied to the grid.

Thanks

 Barry

 

0
Georgi Krustev
Telerik team
answered on 29 Jul 2015, 07:54 AM
Hello Barry,

Basically, when widget uses remote binding, then the server will need to handle the filtration, pagination and etc. That being said, the MultiCheck will send the required parameters to the server and the service in question should return only the correct data set.

The local binding, requires to update the widget manually as it is shown in this Dojo demo.

If I am missing something in the question or you are experiencing any difficulties with the implementation, please send us a repro demo that demonstrates the issue. Thus we will be able to review it locally and advice you further.

Regards,
Georgi Krustev
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Barry
Top achievements
Rank 1
answered on 29 Jul 2015, 12:24 PM

I figured out how I needed to do this. So for anyone else who may have the problem... here is my solution.

 I added a custom data attribute to my grid headers to identity whether my custom multi filter should be used:

.HeaderHtmlAttributes(new { data_multi_filter = ​"True" })

I then hooked up to the FilterMenuInit event on the grid:

.Events(ev => ev.FilterMenuInit("GridFilterMenuInitialized")

 My JS Function for FilterMenuInit looks like this:

 

function GridFilterMenuInitialized(e) {
   
   
        var popup = e.container.data("kendoPopup");
        var parent = popup.options.anchor.parent();
        var fieldName = parent.data("field");
        var gridDataSource = this.dataSource;
        var currentFilters;
 
        if (gridDataSource.filter())
        {
            // Transform the filters that have been applied in the grid to a long string
            currentFilters = gridDataSource.transport.parameterMap({filter: gridDataSource.filter()}).filter;
        }     
     
        if (parent.data("multi-filter") == "True")
        {
            // Only do this for multi-filters
            // Leave the default filter for everything else
             
            // Grab an element in the DOM that we can attach our listview too
            var helpTextElement = $(e.container).children(":first").children(":first");
       
            // Destroy and remove any Kendo List View widget already created for this field
            var isCreated = $('#lst'+fieldName)
            if (isCreated.data("kendoListView"))
            {
                 
                isCreated.data("kendoListView").destroy();
                 
            }
            if (isCreated)
            {
                isCreated.remove();
            }
 
            // Create an instance of a listview
            // We don't actually bind to anything here
            // It is done on the fly in the popup open event (see further down)
            var element = $("<div id='lst" + fieldName + "' class='checkbox-container'></div>").insertAfter(helpTextElement).kendoListView({
                    dataSource: null
                     
                });
             
 
            // Hide all those other dropdown and filtering stuff
            $('.checkbox-container').siblings("span").hide()
            $('.checkbox-container').siblings("input").hide()
 
 
            // Hook up the Filter event
            e.container.find("[type='submit']").click(function (e) {
                e.preventDefault();
                e.stopPropagation();
             
                // Apply whatever have been checked in the checkbox list to the grid
                var filter =gridDataSource.filter() || { logic: "and", filters: [] };
                var fieldFilters = $.map($(element).find(":checkbox:checked"), function (input) {
                    return {
                        field: fieldName,
                        operator: "eq",
                        value: input.value
                    };
                });
                if (fieldFilters.length) {
                    removeFiltersForField(filter, fieldName);
                    filter.filters.push({
                        logic: "or",
                        filters: fieldFilters
                    });
                    gridDataSource.filter(filter);
                }
            
                popup.close();
 
            });
 
            // Hookup the Clear button event
            e.container.find("[type='reset']").click(function (e) {
                e.preventDefault();
                e.stopPropagation();
             
                // clear whatever have been checked in the checkbox list to the grid
                var filter =gridDataSource.filter() || { logic: "and", filters: [] };
                var fieldFilters = $.map($(element).find(":checkbox:checked"), function (input) {
                    return {
                        field: fieldName,
                        operator: "eq",
                        value: input.value
                    };
                });
             
                if (fieldFilters.length) {
                    removeFiltersForField(filter, fieldName);
                    gridDataSource.filter(filter);
                }
            
                popup.close();
 
            });
           
            // bind to the popup open event and do some custom work for multifilters
            e.container.data("kendoPopup").bind("open", function(e) {
       
                if (gridDataSource.filter())
                {
                    // Transform the filters that have been applied in the grid to a long string
                    currentFilters = gridDataSource.transport.parameterMap({filter: gridDataSource.filter()}).filter;
                }  
 
                if (parent.data("multi-filter") == "True")
                {
                    // This is a multi filter lets do some custom stuff
                    var checkboxesDataSource;
 
                       // It's multi filter
                        checkboxesDataSource = new kendo.data.DataSource({
                            transport: {
                                read: {
                                    url: '@Url.Action("GetMultiFilterOptionsForColumn")',
                                    dataType: "json",
                                    data: { field: fieldName, currentFilters: currentFilters }
                                }
                             
                        });
                    }
          
                    // Grab the current ListView
                    var lst = $("#lst" + fieldName).data("kendoListView");
                    var lstOptions = lst.options;
 
                    // Rebind the datasource
                    // This is important as the current filters and/or fieldname may have changed.
                    lstOptions.dataSource = checkboxesDataSource;
                     
                    // rebind the template
                    lstOptions.template = "<div><input type='checkbox' #: check # value='#: fieldvalue #'/>#: fieldtext #</div>";
                     
                    // Destroy the current listview
                    lst.destroy();
                    // and recreate it with the updated datasource options
                    // this will initiate a .dataSource.transport.read() call to the specified URL
                    $("#lst" + fieldName).kendoListView(lstOptions);
                    $("#lst" + fieldName).css({ "height": "300",
                                                "width" : "200",
                                                "overflow" : "scroll"
                                                });
                }
                 
              });
 
        }
 
         
 
 
    }
 
    // Helper function for filtering
    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;
                }
            });
        }
    }

In my Controller I have the following method:

 

public ActionResult GetMultiFilterOptionsForColumn(string field,
           string currentFilters)
       {
           // This gets the possible distinct values for the CURRENT grid items.
 
           currentFilters = currentFilters ?? "";
 
           DataSourceRequest request = new DataSourceRequest();
           request.Filters = Kendo.Mvc.Infrastructure.FilterDescriptorFactory.Create(currentFilters == null ? "" : currentFilters.ToString());
 
          // Here you would call you service/repo and get the data that you need
          // to display dynamically in the filter options.
          // In my case I am returning a list of string values
           var values = _serviceObject.CallMethodToGetAllDistinctDataValues(field, request);
            
           // Construct a new anonymous type to be consumed by the filter menu (converting NULLS to string values)
           var arr = values.Select(c =>
                     new { fieldvalue = (c == null ? "NULL" : c.ToString()),
              fieldtext = (c == null ? "NULL" : c.ToString()),
               check = currentFilters.Contains(field) == true ? "checked" : ""
             }).ToArray();
 
           return Json(arr, JsonRequestBehavior.AllowGet);         
       }

 What happens here is that any column header with the data attribute multi-filter will have a custom checkbox list with the items returned from the controller method. The call to the controller is made when the filter popup opens. There is additional custom code to hook up the Filter and Clear buttons.

If a column does not have the custom data attribute of multi-filter then the default Kendo Filter is displayed.

 

I hope this helps someone else, please do let me know if there are any errors or a misunderstanding of how things work!

 

Thanks

Barry

 

 

 

 

 

0
Mark
Top achievements
Rank 1
answered on 29 Mar 2016, 04:30 PM

Hi Barry

Excellent work but can you please give us the code for var values = _serviceObject.CallMethodToGetAllDistinctDataValues(field, request);

Many thanks

 

 

Tags
Grid
Asked by
Barry
Top achievements
Rank 1
Answers by
Barry
Top achievements
Rank 1
Georgi Krustev
Telerik team
Mark
Top achievements
Rank 1
Share this question
or