Use dropdownlist in grid column filter

3 Answers 4439 Views
Grid
Rich
Top achievements
Rank 1
Rich asked on 14 Dec 2012, 07:09 PM
I would like the column filter to display a dropdownlist instead of a text box so the user can filter the grid based on pre-defined values.  For example, I have a column in my grid called, "Status".  The values can only be "New", "Open", or "Closed".  When I set this column to filterable, the user has to type the word "New" and I would like them to choose the value from a dropdownlist instead.  Is there a way to do this?  I can't find it in the documentation.  Thanks.

3 Answers, 1 is accepted

Sort by
0
Accepted
John DeVight
Top achievements
Rank 1
answered on 14 Dec 2012, 07:47 PM

Hi Rich,

Yes it is possible to do this with a bit of extra code.  After you create the grid, get a reference to the filter menu.  Locate the textbox in the filter menu and initialize it as a dropdownlist.

I've actually done something very similar and have a jsFiddle demonstrating it.  The jsFiddle is located at: http://jsfiddle.net/jddevight/wGjCZ/

I have the following code to create a grid:

// Define the datasource for the grid.
var _peopleDataSource = new kendo.data.DataSource({
    data: [
        { id: 1, name: "John", roleId: 1, roleTitle: "Software Engineer" },
        { id: 2, name: "Dave", roleId: 2, roleTitle: "Quality Assurance Engineer" },
        { id: 3, name: "Aaron", roleId: 3, roleTitle: "Team Lead" }
    ]
});
  
// Create the grid.
var _grid = $("#grid").kendoGrid({
    dataSource: _peopleDataSource,
    filterable: { extra: false },
    columns: [
        {
            field: "name",
            title: "Name"
        },{
            field: "roleTitle",
            title: "Role"
        }
    ],
    editable: true
}).data("kendoGrid");

Here is the code to get the filter menu for the "Role" column (the CSS query assumes that the filtermenu that I want is for the last column):
// Find the Role filter menu.
var filterMenu = _grid.thead.find("th:not(.k-hierarchy-cell,.k-group-cell):last").data("kendoFilterMenu");
If you need to get the filter menu for a different column, lets say, the 2nd column, then the code would look like this:
// Find the filter menu for the second column.
var filterMenu = $(_grid.thead.find("th:not(.k-hierarchy-cell,.k-group-cell)")[1]).data("kendoFilterMenu");

And finally, here is the code to convert the textbox to a dropdownlist:
// Change the text field to a dropdownlist in the Role filter menu.
filterMenu.form.find(".k-textbox:first")
    .removeClass("k-textbox")
    .kendoDropDownList({
        dataSource: new kendo.data.DataSource({
            data: [
                { title: "Software Engineer" },
                { title: "Quality Assurance Engineer" },
                { title: "Team Lead" }
            ]
        }),
        dataTextField: "title",
        dataValueField: "title"
    });
Hope this helps...

Regards,

John DeVight
Marcin Butlak
Top achievements
Rank 2
commented on 14 Dec 2012, 07:59 PM

Nice hack but still kendui team should provide a nice way to hook-up our custom filter, nevertheless thanks for sharing :)
Rich
Top achievements
Rank 1
commented on 17 Dec 2012, 02:21 PM

Thanks for both of your responses!  John, I ended up using your solution and it works great.  One more question:  Is there a way I can hide the dropdownlist with the conditional values ("is equal to", "contains", etc.)?

thanks for your help.
John DeVight
Top achievements
Rank 1
commented on 28 Dec 2012, 01:18 PM

Hi Rich,

Yes, you can hide the dropdownlist with the conditional values with the following:

filterMenu.form.find("span.k-dropdown:first").css("display", "none");

You can also change the text that appears in the filter menu so that it makes a bit more sense with how you are using it:

filterMenu.form.find("div.k-filter-help-text").text("Select an item from the list:");
I've updated the jsFiddle to demonstrate: http://jsfiddle.net/jddevight/wGjCZ/

 Regards,

John DeVight

Michael
Top achievements
Rank 1
commented on 21 Mar 2013, 05:09 PM

I was using this solution and it was working great with Kendo version 2012.3.1315, but when I upgraded to version 2013.1.319 the "filterMenu.form" object is undefined.  So, when I execute this code:

var grid = $("#BartSelectedProjectsGrid");
// Get the filter menu for the third column in the grid
var filterMenu = $(grid.find("th:not(.k-hierarchy-cell,.k-group-cell)")[2]).data("kendoFilterMenu");
//modify the default help text
filterMenu.form.find("div.k-filter-help-text").text("Select an item from the list:");

It gives me this error (on the last line of code):

Microsoft JScript runtime error: Unable to get value of the property 'find': object is null or undefined

Again, this code worked fine with version 2012.3.1315 but now it's broken in version 2013.1.319.  Any suggestions on how to modify this code to get it to work in the new version?

John DeVight
Top achievements
Rank 1
commented on 21 Mar 2013, 05:57 PM

Hi Michael,

I'll look into it now and get back to you shortly....

Regards,

John DeVight
0
Marcin Butlak
Top achievements
Rank 2
answered on 14 Dec 2012, 07:35 PM
The grid doesn't provide any nice way to hook-up a custom filter in the column header but you can customize the column header template to imitate a filter http://docs.kendoui.com/api/web/grid#columnsheadertemplate-string or you can create a filter in the toolbar like in this example: http://demos.kendoui.com/web/grid/toolbar-template.html
0
John DeVight
Top achievements
Rank 1
answered on 21 Mar 2013, 06:58 PM
Hi Michael,

I looked at the source code for 2013.1.319 and it appears that with this release, the kendo framework is not creating the filter form until it is actually needed.  The kendo grid raises a "filterMenuInit" event when any of the filter forms are initialized.  In the parameter passed in is the field associated with the filter and a reference to the form which is referred to as "container".

I was unable to get the example working on jsFiddle, but I was able to get the example working on my local workstation.  Here is the entire code:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
    <div class="title">Instructions</div>
    <div id="instructions">The first textbox in the Role filter menu has been converted to a Kendo DropDownList.  Click on the filter icon in the Role column heading to see.</div>
    <div class="title">Person Grid</div>
    <div id="grid"></div>
 
    <script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
    <script>
        $(document).ready(function() {
            // Define the datasource for the grid.
            var _peopleDataSource = new kendo.data.DataSource({
                data: [
                    { id: 1, name: "John", roleId: 1, roleTitle: "Software Engineer" },
                    { id: 2, name: "Dave", roleId: 2, roleTitle: "Quality Assurance Engineer" },
                    { id: 3, name: "Aaron", roleId: 3, roleTitle: "Team Lead" }
                ]
            });
 
            // Create the grid.
            var _grid = $("#grid").kendoGrid({
                dataSource: _peopleDataSource,
                filterable: { extra: false },
                columns: [
                    {
                        field: "name",
                        title: "Name"
                    },{
                        field: "roleTitle",
                        title: "Role"
                    }
                ],
                editable: true
            }).data("kendoGrid");
 
            // The filterMenuInit event is raised when the filter menu is initialized.
            _grid.bind("filterMenuInit", function (e) {
                 
                // If the filter is for the "Role" column...
                if (e.field == "roleTitle") {
                    e.container.find("div.k-filter-help-text").text("Select an item from the list:");
                    e.container.find("span.k-dropdown:first").css("display", "none");
                 
                    // Change the text field to a dropdownlist in the Role filter menu.
                    e.container.find(".k-textbox:first")
                        .removeClass("k-textbox")
                        .kendoDropDownList({
                            dataSource: new kendo.data.DataSource({
                                data: [
                                    { title: "Software Engineer" },
                                    { title: "Quality Assurance Engineer" },
                                    { title: "Team Lead" }
                                ]
                            }),
                            dataTextField: "title",
                            dataValueField: "title"
                        });
                }
            });
        });
    </script>
<body>
</html>

Let me know if you have any questions / problems with this.

Regards,

John DeVight

Michael
Top achievements
Rank 1
commented on 22 Mar 2013, 02:57 PM

Yes!  That worked great.  Thanks for the quick response!

Mike
Dilshan
Top achievements
Rank 1
commented on 26 Mar 2013, 03:32 PM

Hey John:

your example works perfect except one thing.

If you open the page and do not change any filter,  just click "Filter" button,  It should filter by "Software Engineer" since that is the default value of drop down, but it actually does not filter by that.  if you change to another filter and click "Filter" button, and then change back to "Software Engineer" and click "Filter" again, it will work.

Can you tell us how to fix this issue?
 
Thanks.
Michael
Top achievements
Rank 1
commented on 26 Mar 2013, 03:37 PM

That's a great question.  I had the same problem.  I got around it by adding a blank value in my dropdown list, so the blank value is the default value of the list and if the user wants to filter on a "real" value then they would choose it and click "Filter".  That works, but it's not ideal and it would be great to figure out how to fix the underlying problem.

Thanks,

Mike
John DeVight
Top achievements
Rank 1
commented on 27 Mar 2013, 12:22 PM

I'll take a look at that now and see what I can figure out...

Regards,

John DeVight
John DeVight
Top achievements
Rank 1
commented on 27 Mar 2013, 01:50 PM

At the bottom of this post is an updated solution that will set the filter value to the first item in the dropdownlist ("Software Engineer") when the filter dialog is displayed.

When filtering is enabled, each column heading has a kendoFilterMenu object associated with it.  The kendoFilterMenu has a filterModel object with a filters array.  There are 2 objects in the filter array, the first object for the first filter field and the second object for the second filter field.  In my example, I've hidden the second filter field, so I'm only concerned with the first filter object (kendoFilterMenu.filterModel.filters[0]).

I got the kendoFilterMenu object for the last column in the grid with the following code:
_grid.thead.find("th:last").data("kendoFilterMenu")
I then set the filterModel.filters[0].value to the title of the first item in the kendoDropDownList with the following code:
_grid.thead.find("th:last").data("kendoFilterMenu").filterModel.filters[0].value = dropDownList.dataSource.data()[0].title;
Here is the entire solution.
<!DOCTYPE html>
<html>
<head>
</head>
<body>
    <div class="title">Instructions</div>
    <div id="instructions">The first textbox in the Role filter menu has been converted to a Kendo DropDownList.  Click on the filter icon in the Role column heading to see.</div>
    <div class="title">Person Grid</div>
    <div id="grid"></div>
 
    <script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
    <script>
        $(document).ready(function() {
            // Define the datasource for the grid.
            var _peopleDataSource = new kendo.data.DataSource({
                data: [
                    { id: 1, name: "John", roleId: 1, roleTitle: "Software Engineer" },
                    { id: 2, name: "Dave", roleId: 2, roleTitle: "Quality Assurance Engineer" },
                    { id: 3, name: "Aaron", roleId: 3, roleTitle: "Team Lead" }
                ]
            });
 
            // Create the grid.
            var _grid = $("#grid").kendoGrid({
                dataSource: _peopleDataSource,
                filterable: { extra: false },
                columns: [
                    {
                        field: "name",
                        title: "Name"
                    },{
                        field: "roleTitle",
                        title: "Role"
                    }
                ],
                editable: true
            }).data("kendoGrid");
 
            // The filterMenuInit event is raised when the filter menu is initialized.
            _grid.bind("filterMenuInit", function (e) {
                 
                // If the filter is for the "Role" column...
                if (e.field == "roleTitle") {
                    e.container.find("div.k-filter-help-text").text("Select an item from the list:");
                    e.container.find("span.k-dropdown:first").css("display", "none");
                 
                    // Change the text field to a dropdownlist in the Role filter menu.
                    var dropDownList = e.container.find(".k-textbox:first")
                        .removeClass("k-textbox")
                        .kendoDropDownList({
                            dataSource: new kendo.data.DataSource({
                                data: [
                                    { title: "Software Engineer" },
                                    { title: "Quality Assurance Engineer" },
                                    { title: "Team Lead" }
                                ]
                            }),
                            dataTextField: "title",
                            dataValueField: "title"
                        }).data("kendoDropDownList");
                     
                    // Get the FilterMenu object for the roleTitle column.
                    // Set the FilterMenu.filterModel.filters[0] to the
                    // title of the first item in the dropdownlist.
                    _grid.thead.find("th:last")     /* roleTitle is the last column */
                        .data("kendoFilterMenu")    /* Get the FilterMenu for the last column */
                            .filterModel.filters[0].value = dropDownList.dataSource.data()[0].title;
                }
            });
        });
    </script>
<body>
</html>

Hope that helps :-)

Regards,

John DeVight
Dilshan
Top achievements
Rank 1
commented on 27 Mar 2013, 02:09 PM

Thanks a lot John. This works perfect.

There is still a bug with the code, if you click "clear" button first, and then click "Filter" button again, it won't filter properly. I think the same code needs to be set when "Clear" button gets clicked.


So I changed last part of code to be:


                    // Get the FilterMenu object for the roleTitle column.
                    // Set the FilterMenu.filterModel.filters[0] to the
                    // title of the first item in the dropdownlist.
                    var filterMenu = _grid.thead.find("th:last")     /* roleTitle is the last column */
                        .data("kendoFilterMenu");    /* Get the FilterMenu for the last column */
                    filterMenu.filterModel.filters[0].value = dropDownList.dataSource.data()[0].title;
                            
                    filterMenu.form.bind('reset', function() {
                    filterMenu .filterModel.filters[0].value = dropDownList.dataSource.data()[0].title;
                });

This will fix the bug.
  
John DeVight
Top achievements
Rank 1
commented on 27 Mar 2013, 05:09 PM

Thanks for catching that issue and posting a solution :-)
Tom
Top achievements
Rank 1
commented on 27 Sep 2016, 08:37 PM

Have there been any updates since this old thread to support custom column filters?
Alex Hajigeorgieva
Telerik team
commented on 30 Sep 2016, 08:18 AM

Hi Tom,

Please accept my apology for the delay in responding.

Indeed, there is an update. The Kendo UI Team has created a nice and easy way for our clients to implement a DropDown List as a Filter Menu among other features which provide more freedom as far as filter customizations as concerned.

All you have to do now is add the columns filterable UI configuration setting and initialize the UI of your preference:

http://docs.telerik.com/kendo-ui/api/javascript/ui/grid#configuration-columns.filterable.ui

A live demo is available at: http://demos.telerik.com/kendo-ui/grid/filter-menu-customization

Kind Regards,
Alex
Telerik by Progress
 
Get started with Kendo UI in days. Online training courses help you quickly implement components into your apps.
Bob
Top achievements
Rank 1
commented on 10 May 2017, 02:04 PM

Hi Alex,

Tried your example at: http://demos.telerik.com/kendo-ui/grid/filter-menu-customization

However, if you remove the filterable function on the "title" filter

filterable: { ui: titleFilter }

So you are left with just a normal text search.

Then try filtering a few cities, then go to the title column, the cities appear in a drop down list for the title column.

I think that this could be Edge doing an auto-complete.

Any idea how to stop it?

Bob
Top achievements
Rank 1
commented on 10 May 2017, 02:15 PM

Hi Alex,

I should have been a bit clearer.

This issue only seems to affect Microsoft Edge, its OK in Chrome / Firefox.

Alex Hajigeorgieva
Telerik team
commented on 12 May 2017, 10:45 AM

Hello Bob,

It seems that Edge adds this via advanced settings - Save Form Entries. If it is turned off, the latest form entries are not saved and not displayed when typing in inputs:



Regards,
Alex Hajigeorgieva
Telerik by Progress
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 (charts) and form elements.
Tags
Grid
Asked by
Rich
Top achievements
Rank 1
Answers by
John DeVight
Top achievements
Rank 1
Marcin Butlak
Top achievements
Rank 2
Share this question
or