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

Cascade filter using ajax binding

4 Answers 251 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Alexandra
Top achievements
Rank 1
Alexandra asked on 13 Jun 2017, 10:34 AM

Hi,

I have a grid with 2 fields that are connected so a cascade filter needs to be done on them. I manage to do this using Server binding because the UI was refreshed when a filter was done. But now I have to use Ajax binding but the cascade code does not work anymore because the UI is no longer called again

@(Html.Kendo().Grid<TelerikTestModel>()
            .Name("grid2")
            .Columns(columns =>
            {
                columns.Bound(product => product.MainField).UI("mainFilter"));
                columns.Bound(product => product.DependentField).UI("subFilter"));
            })
            //                                   .Server()
            .DataSource(dataSource => dataSource.Ajax().PageSize(10).Read(read => read.Action("Data_Read", "Home")))
            .HtmlAttributes(new { style = "height: 550px;", @class = "myClass" })
            .Pageable(x => x.ButtonCount(5))
            .Sortable()
            .Filterable()
            .Scrollable()
            //.ColumnMenu()
            .Resizable(resize => resize.Columns(true))
            .Reorderable(reorder => reorder.Columns(true))
            .Events(e => e.FilterMenuInit("filterMenuInit"))
)


function mainFilter(element) {
        element.kendoDropDownList({
            dataSource: {
                transport: {
                    read: "@Url.Action("FilterMenuCustomization_MainFilter")"
                }
            },
            optionLabel: "--Select Value--",
            name: "mainFilter",
        });
    }
 
    function subFilter(element) {
 
        var dataSource = $("#grid").data("kendoGrid").dataSource;
 
        var filter = dataSource.filter();
 
        var value = -1
        if (filter && filter.filters) {
            var result = $.grep(filter.filters, function (e) {
                return e.field == "MainField";
            });
 
            if (result.length == 1) {
                value = result[0].value;
            }
        }
 
        element.kendoDropDownList({
            dataSource: {
                transport: {
                    read: {
                        url: "@Url.Action("FilterMenuCustomization_SubFilter")",
                        dataType: "json",
                        data: {
                            mainFilter: value,
                        }
                    }
                }
            },
            optionLabel: "--Select Value--",
            name: "subFilter",
        });
    }

Two questions:
1. in subFilter is there a way to get to the grid datasource without using the grid id? I need to make this code be used by any grid that has a dependent list
2. for the Ajax-binding I was thinking to use the onFiltering event but how can I get to the filter control (to do the subFilter code)? On a page with 2 grids and the same dependent cascade filters I could not find a connection between the grid and the filter controls.

4 Answers, 1 is accepted

Sort by
0
Tsvetina
Telerik team
answered on 15 Jun 2017, 09:22 AM
Hello Alexandra,

I think that the filterMenuOpen event will help you with both your questions. It fires each time the filter menu is opened, so you can use it to check if a new filter was applied to the Grid and filter the child DropDownList based on it. 
Using this event, you will be able to access the Grid from the event arguments (e.sender), so you don't need to find it by hard-coded id. Additionally, you have a reference to the currently opened filter menu element, so you can find the child DropDownList inside it, using a jQuery selector.

Since the fluent API is currently missing a definition for FilterMenuOpen event, you can manually add a client event handler once the Grid is created (in the DataBound event).
.Events(events=>events.DataBound("dataBound"))
function dataBound(e) {
    e.sender.unbind("filterMenuOpen", filterMenuOpen);
    e.sender.bind("filterMenuOpen", filterMenuOpen);
}

I am calling unbind before bind, because without it a new event handler would be added with each re-bind of the Grid, resulting in filterMenuOpen executing multiple times in a row. Once the missing event is added to the fluent API, you will not need this. I logged an issue for you to follow here.

Regards,
Tsvetina
Progress Telerik
Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Alexandra
Top achievements
Rank 1
answered on 15 Jun 2017, 03:11 PM
Hi Tsvetina,

Thank you for the suggestion. Can you help me also to rebind the dropdown list.

Here is the code
function filterMenuOpen(e) {
    if (e.field == "DependentField") {
        var dataSource = e.sender.dataSource;
 
        var filter = dataSource.filter();
 
        var value = -1
        // determine value correctly
 
        // this line seems to work
        e.container.find(".k-filter-help-text").text("Show sub functions from menu:");
 
        // this line return undefined regardless of what filter I try
        //var dropdownlist = e.container.find("[data-role=dropdownlist]:eq(1)").data("kendoDropDownList");
        //var dropdownlist = e.container.find("[data-role=listbox]:eq(1)").data("kendoListBox");
        var dropdownlist = e.container.find("[data-role=subfilter]").data("kendoDropDownList");
        var dataSource = new kendo.data.DataSource({
            transport: {
                read: {
                    url: "@Url.Action("FilterMenuCustomization_SubFilter")",
                    dataType: "json",
                    data: {
                        mainFilter: value,
                    },
                },
            },
        });
        // this is line :219:13
        dropdownlist.setDataSource(dataSource)
    }
}


And on console I get this error:
jQuery.Deferred exception: Unable to get property 'setDataSource' of undefined or null reference TypeError: Unable to get property 'setDataSource' of undefined or null reference
   at filterMenuOpen (http://localhost:62884/:219:13)
   at trigger (http://localhost:62884/Scripts/kendo/kendo.all.min.js:25:6789)
0
Accepted
Tsvetina
Telerik team
answered on 15 Jun 2017, 03:37 PM
Hi Alexandra,

It seems like you are not able to access the DropDownList element and the widget reference is null. Try inspecting the output of the DropDownList to see the exact attributes and classes applied. I tested the custom filter menu demo and I could access the span wrapper of the DropDownList, based on its title attribute set to "Value" by the Grid:
http://dojo.telerik.com/@tsveti/aVIPi

filterMenuOpen: function(e){
  if(e.field=="City"){
    var ddl = $("span[title='Value'] input").data("kendoDropDownList");
    alert(ddl.value());
  }
}


Regards,
Tsvetina
Progress Telerik
Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Alexandra
Top achievements
Rank 1
answered on 28 Aug 2017, 08:35 AM

Hi Tsvetina,

Thank you for the help. We manage to get the cascade filter to work. We had to implement also the filter event in order to remove the cascade filter but for that we did not require much help.

Tags
Grid
Asked by
Alexandra
Top achievements
Rank 1
Answers by
Tsvetina
Telerik team
Alexandra
Top achievements
Rank 1
Share this question
or