Refresh multi checkbox filter options when grid is filtered

15 posts, 1 answers
  1. Jonas Nygaard
    Jonas Nygaard avatar
    3 posts
    Member since:
    Sep 2012

    Posted 14 Sep 2015 Link to this post

    How do I force a refresh of the filter menu item in a grid column when the grid is filtered after filterMenuItem has been fired?

    The grid data source is having an initial filter, that might make the grid empty at initialization.

    Scenario 1: 

    If I click on one of the grid column filter buttons (let us call it ReviewStatus) with a multi check box filter (filterMenuItem is fired), then there is of course no options available when the grid is empty. If I then clear all filters on the data source by calling grid.dataSource.filter({}) and the grid is now having rows, then there is still no options available in the ReviewStatus filter.

    Scenario 2: 

    The first thing I do is to clear all filters such that there is rows available in the grid. If I use a multi check filter on one of the other columns to filter the grid then the options in ReviewStatus will be updated accordingly.

    How do I force the filter menu item to sync the data source with the grid data source after the filter menu item is initialized?

    My grid has a the following grid options:

    dataSource:{ 
        type: "odata",
         serverFiltering: true,
         serverSorting: true,

         filter:{ field: "Country": operator: "eq", value: "UK" }

    },

    columns: [
        { field: "ReviewStatus", filterable: { multi: true } },
        { field: "​Country", filterable: { multi: true } },
        { field: "Severity", filterable: { multi: true } },
        { field: "SensorName", filterable: { multi: true } }

    ],

    filterable: true,

    navigatable: true,
    selectable: "multiple",
    resizable: true,
    reorderable: true,
    sortable: true,
    columnMenu: false,
    pageable: false

     
  2. Answer
    Boyan Dimitrov
    Admin
    Boyan Dimitrov avatar
    1746 posts

    Posted 16 Sep 2015 Link to this post

    Hello Jonas Nygaard,

     

    When filter multi checkboxes are used, they are populated only once, when the respective filtering menu is opened for the first time. This ensures good performance and avoids repetitive and unnecessary HTTP requests. By design, the checkboxes's data is refreshed automatically in the following cases:

    - the Grid dataSource is replaced via the setDataSource method
    - a Grid data item is added, removed or modified

     

     

     Given this my recommendations would be:

    - use setDataSource to toggle the Grid data. This has two benefits - the checkboxes' data will refresh automatically, and also, the custom business logic will integrate better with the Grid functionality.
    http://dojo.telerik.com/oKerE/4

    - use a separate DataSource instance for the checkboxes data, and call its read() method when the Grid data is toggled
    http://dojo.telerik.com/IjEre

    - there is third option - define one DataSource instance and assign it to both the Grid and in columns.filterable.dataSource. This will refresh the checkbox data automatically, but if you filter the Grid data via the Grid UI, you will also filter (reduce) the checkbox items.

    http://dojo.telerik.com/AyEca/2

     

    Regards,
    Boyan Dimitrov
    Telerik
     
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
     
  3. Kendo UI is VS 2017 Ready
  4. Jonas Nygaard
    Jonas Nygaard avatar
    3 posts
    Member since:
    Sep 2012

    Posted 17 Sep 2015 in reply to Boyan Dimitrov Link to this post

    I like the third option where the checkbox items are reduced as the grid is filtered. I can, however, not get it to work properly. Instead of having unique checkbox items I get an item for each row in the grid.

    I am using angularjs and am setting the grid data source to the multi filterables just before setting the grid options on the angular scope.

    I have the first option working where I use grid.setDataSource() when serverFiltering is enabled and use grid.dataSource.filter() serverFiltering is disabled.

  5. Petyo
    Admin
    Petyo avatar
    2438 posts

    Posted 21 Sep 2015 Link to this post

    Hello Jonas Nygaard,

     

    this seems strange - can you modify the example provided by Boyan so that we may exhibit the problem on our side? Thank you in advance.

     

    Regards,
    Petyo
    Telerik
     
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
     
  6. Jonas Nygaard
    Jonas Nygaard avatar
    3 posts
    Member since:
    Sep 2012

    Posted 22 Sep 2015 in reply to Petyo Link to this post

    In http://dojo.telerik.com/AyEca/2

    Try filtering Unit Price by selecting $18.00 and $19.00. Then open the Unit Price filter again and you will see 4 $18.00 and 2 $19.00 checkbox items.

  7. Boyan Dimitrov
    Admin
    Boyan Dimitrov avatar
    1746 posts

    Posted 24 Sep 2015 Link to this post

    Hello Jonas Nygaard,

    Indeed the logic for finding and displaying the distinct(unique) values will not be executed in case of using same DataSource instance for the Kendo UI Grid and multi filter check box. 

    I would suggest to use the following approach in order to refresh the multi checkbox filter options:

    $(".k-grid-filter").click(function(e){
                        var fmc = $(e.target).closest("th").data("kendoFilterMultiCheck");
                        fmc.checkSource.read();
                        fmc.container.empty();
                        fmc.refresh();
                      });

    Please refer to the http://dojo.telerik.com/oKerE/14 example. 

    Regards,
    Boyan Dimitrov
    Telerik
     
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
     
  8. Eddie
    Eddie avatar
    4 posts
    Member since:
    Jun 2015

    Posted 12 Oct 2015 in reply to Boyan Dimitrov Link to this post

    How would the third option be applied to a MVC application of a Kendo Grid?
  9. Sean
    Sean avatar
    1 posts
    Member since:
    Sep 2014

    Posted 12 Oct 2015 Link to this post

    I was able to fix this globally for my app (without performance impact) by overriding these two methods on kendoFilterMultiCheck (TypeScript)

            refresh(e: any): void {
                var didChange = false;
                this.checkSource.one("change",() => {
                    didChange = true;
                });

                super.refresh(e);

                if (!didChange && this.form && e && this.options.forceUnique && e.sender === this.dataSource && !this.dataSource.options.serverPaging) {
                    this.isStale = true;
                }
            }

            protected _click(e: JQueryEventObject): void {
                if (this.isStale) {
                    this.isStale = false;
                    var field = this.field;
                    this.checkSource.data(this.dataSource.data().slice(0).distinct(t => <any>t[field]));
                    this.container.empty();
                    this.createCheckBoxes();
                }
                super._click(e);
            }

     

    distinct() is our own addition to the Array prototype.

  10. Lotux
    Lotux avatar
    3 posts
    Member since:
    Feb 2016

    Posted 08 Mar in reply to Sean Link to this post

    Hi Sean,

    When you say you override it, you actually change the Kendo JS file or did you extend it?

  11. Raul
    Raul avatar
    15 posts
    Member since:
    Apr 2016

    Posted 11 Oct in reply to Boyan Dimitrov Link to this post

    Hi Bojan,

    I was looking for a similar behavior in my project as the third option presented by you. I am using asp.net instead of html5.

    This is my kendo grid definition in the view :

    <div class="grid-container-fluid">
        @(Html.Kendo().Grid<ManageSuperUserViewModel>()
                .Name("ManageSuperuserGrid")
                .ToolBar(tools => tools.Excel())
                .Excel(excel => excel
                    .FileName("Super Users List.xlsx")
                    .AllPages(true)
                )
            .Columns(columns =>
            {
                columns.Bound(x => x.Id).Visible(false);
                columns.Bound(x => x.L1Process.Name).Width(200).Filterable(ftb => ftb.Multi(true).Search(true).DataSource(ds => ds
                .Read(r => r
                    .Action("L1ProcessReadNameValues", "SuperUser")
                ))).HeaderHtmlAttributes(new { style = "overflow: visible; white-space: normal" }).Title("L1 Process");
                columns.Bound(x => x.User.UserNameDescriptive).Width(220).Filterable(ftb => ftb.Multi(true).Search(true).DataSource(ds => ds
                .Read(r => r
                    .Action("UserReadNameValues", "SuperUser")
                    .Type(HttpVerbs.Post)
                ))).HeaderHtmlAttributes(new { style = "overflow: visible; white-space: normal" }).Title("Super User Names");
                columns.Bound(x => x.Profile.Name).Width(250).Filterable(ftb => ftb.Multi(true).Search(true).DataSource(ds => ds
                .Read(r => r
                    .Action("UserProfileNameValues", "SuperUser")
                    .Type(HttpVerbs.Post)
                ))).HeaderHtmlAttributes(new { style = "overflow: visible; white-space: normal" }).Title("Profile Names");
                columns.Bound(x => x.RoleType.Name).Width(150).Filterable(ftb => ftb.Multi(true).Search(true).DataSource(ds => ds
                .Read(r => r
                    .Action("UserRoleTypeNameValues", "SuperUser")
                    .Type(HttpVerbs.Post)
                ))).HeaderHtmlAttributes(new { style = "overflow: visible; white-space: normal" }).Title("Role Types");
                columns.Bound(x => x.BusinessUnit.Name).Width(150).Filterable(ftb => ftb.Multi(true).Search(true).DataSource(ds => ds
                .Read(r => r
                    .Action("UserBusinessUnitNameValues", "SuperUser")
                    .Type(HttpVerbs.Post)
                ))).HeaderHtmlAttributes(new { style = "overflow: visible; white-space: normal" }).Title("Business Org 1");
                columns.Bound(x => x.Market.Name).Width(150).Filterable(ftb => ftb.Multi(true).Search(true).DataSource(ds => ds
                .Read(r => r
                    .Action("UserMarketNameValues", "SuperUser")
                ))).HeaderHtmlAttributes(new { style = "overflow: visible; white-space: normal" }).Title("Business Org 2");
                columns.Bound(x => x.BusinessType.Name).Width(150).Filterable(ftb => ftb.Multi(true).Search(true).DataSource(ds => ds
                .Read(r => r
                    .Action("UserBusinessTypeNameValues", "SuperUser")
                    .Type(HttpVerbs.Post)
                ))).HeaderHtmlAttributes(new { style = "overflow: visible; white-space: normal" }).Title("Business Org 3");

                columns.Bound(x => x.ProcessRole.ProcessRoleId).Width(100).Title("ProcessRole").Filterable(false).Visible(false);
                columns.Bound(x => x.CanEdit).Visible(false);
                columns.Command(command =>
                {
                    if(user.CanManageSuperUser() || User.IsInRole("Administrator") || user.IsInProcessRole(Enums.ProcessRolesEnum.GPD) || user.IsInProcessRole(Enums.ProcessRolesEnum.Delegates))
                    {
                        command.Edit().UpdateText("Save").CancelText("Cancel").Text("Edit");
                        //command.Destroy();
                        command.Custom("Delete").Click("deleteRow");
                    }
                }).Width(180);
            })
            .DataSource(dataSource => dataSource
                .Ajax()
                .PageSize(50)
                //.ServerOperation(false)
                .Model(model =>
                {
                    model.Id(p => p.Id);
                })
                .Read(read => read.Action("GetUserDetails", "SuperUser"))
                .Create(create => create.Action("AddUserDetails", "SuperUser"))
                .Update(update => update.Action("UpdateUserDetails", "SuperUser"))
                //.Destroy(destroy => destroy.Action("DeleteUserDetails", "SuperUser"))

                .Sort(sort =>
                {
                    sort.Add(profile => profile.Profile.Name);
                })
                )
                .ToolBar(toolbar =>
                {
                    if (user.CanManageSuperUser() || User.IsInRole("Administrator") || user.IsInProcessRole(Enums.ProcessRolesEnum.GPD) || user.IsInProcessRole(Enums.ProcessRolesEnum.Delegates))
                    {
                        toolbar.Create().Text("Add New SuperUser");
                    }
                    toolbar.Custom().Name("Clear").Text("Clear All Filters").Url("#").HtmlAttributes(new { onclick = "clearAllFilters()" });
                })
            .Editable(editable => editable.Mode(GridEditMode.PopUp).TemplateName("SuperuserEdit").Window(window => { window.Width(1000); }).DisplayDeleteConfirmation(true))
            .Filterable()
            .Resizable(resize => resize.Columns(true))
            .Scrollable()
            .Sortable(sortable =>
            {
                sortable.AllowUnsort(false);
                //sortable.SortMode(GridSortMode.MultipleColumn);
            })
            .Reorderable(reorderable => reorderable.Columns(true))
            .Pageable(pageable => pageable
                .Refresh(true)
                .PageSizes(true)
                .PageSizes(new int[] { 50, 100, 200, 300, 400, 500 })
                .ButtonCount(5))
            .Events(events =>
            {
                events.Edit("onEditManageSuperuserGrid");
                events.DataBound("onDataBoundManageSuperuserGrid");
                //events.FilterMenuInit("filterMenuInit");
            })
        )
    </div>

    This definition of kendo grid refreshes the filters when the user click in the icon because in the event I am implementing this solution :

            $(".k-grid-filter").click(function (e) {
                var fmc = $(e.target).closest("th").data("kendoFilterMultiCheck");
                fmc.checkSource.read();
                //fmc.container.empty();
                fmc.refresh();
            });

     

    I am always uploading all the data in the filter everytime the user clicks on filter icon. But I don't want this solution, I want only to upload in the filters the possible values that exist in the datasource of the grid. (Similar as your behavior in the option three explained upper).

    I would be extremely grateful if you could help me in this matter.

    Could you tell me how to assign the same datasource in asp.net?

    Best Regards.

    Raúl.

     

     

  12. Boyan Dimitrov
    Admin
    Boyan Dimitrov avatar
    1746 posts

    Posted 12 Oct Link to this post

    Hello Raul,

    A possible solution would be passing some data to the checkSource of the kendoFilterMultiCheck widget. The checkSource is a Kendo UI DataSource instance which contains the unique items in the Kendo UI Grid (according to the entire data for the Kendo UI Grid). The easist way to change the items shown when  kendoFilterMultiCheck is opened is to pass an array of items to the data method of the checkSource. Please refer to the code snippet below: 

     

    fmc.checkSource.data([{LastName: "test"}, {LastName: "test2"}])

     

    Regards,
    Boyan Dimitrov
    Telerik by Progress
     
    Get started with Kendo UI in days. Online training courses help you quickly implement components into your apps.
     
  13. Raul
    Raul avatar
    15 posts
    Member since:
    Apr 2016

    Posted 13 Oct in reply to Boyan Dimitrov Link to this post

    Hello Boyan,

    Thank you for you quick reply ... 

    I want a solution like you use in the third option ('http://dojo.telerik.com/AyEca/2'). Datasource of the Grid is synchronized with the KendofilterMultiCheck. The problem is that you are using HTML script and I am using asp.net code.

    Could you please translate your code in HTML to asp.net in order to see how you are configuring the kendo grid and how you are defining the datasource?.

    Thanks in advanced.

    Raúl.

  14. Boyan Dimitrov
    Admin
    Boyan Dimitrov avatar
    1746 posts

    Posted 14 Oct Link to this post

    Hello Raul,

    I am afraid that in the context of ASP.NET MVC wrappers the DataSource instance are created automatically. Given this developer is not able to define shared DataSource (Kendo UI Grid and the FilterMultiCheckBox widget share same DataSource instance). 

    Regards,
    Boyan Dimitrov
    Telerik by Progress
     
    Get started with Kendo UI in days. Online training courses help you quickly implement components into your apps.
     
  15. Raul
    Raul avatar
    15 posts
    Member since:
    Apr 2016

    Posted 14 Oct in reply to Boyan Dimitrov Link to this post

    Hello Boyan,

    Thank you for your reply ...

    As workaround to this limitation ... Could I access to the Grid DataSource when  kendoFilterMultiCheck is opened?

    My idea is populate the filter that the user is clicking with the different values of the Grid Datasource that exist in the column selected.

    I pretend to populate the filter in the 'data' method of the checkSource.:

            $(".k-grid-filter").click(function (e) {
                var fmc = $(e.target).closest("th").data("kendoFilterMultiCheck");

                !!!! --------------------   Here your code ----------------------------------- !!!!!!
                //fmc.checkSource.read();
                fmc.refresh();
            });

     

    Using the event of the filter (k-grid-filter) and 'data' method like in your example -->  fmc.checkSource.data([{LastName: "test"}, {LastName: "test2"}])

    Can you provide one or several sentences to obtain an array with the different values of the Grid DataSource when the event click of the filter is fired?

    Thanks in advanced.

    Raúl.

     

     

     

  16. Boyan Dimitrov
    Admin
    Boyan Dimitrov avatar
    1746 posts

    Posted 18 Oct Link to this post

    Hello Raul,

    A reference to the DataSource associated with Kendo UI Grid can be accessed by using the property dataSource of the Kendo UI Grid instance. Once there is a reference to the DataSource instance the data method can be used in order to get the data items from the DataSource. 

    Regards,
    Boyan Dimitrov
    Telerik by Progress
     
    Get started with Kendo UI in days. Online training courses help you quickly implement components into your apps.
     
Back to Top
Kendo UI is VS 2017 Ready