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

How to define a Kendo grid Column filter between two dates?

21 Answers 3733 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Mahlon
Top achievements
Rank 1
Mahlon asked on 01 Aug 2014, 01:43 PM
In our application we want the filter on a date column to prompt the user for a start date and an end date, with the filter returning rows where the field in question falls between (or on) those two dates.

Initial Approach

Our initial approach was to restrict date types to use gte and lte operators, and add the "extra : true" filterable option on the column. This came close, but presented the following problems: A) Each date input could use either the gte (Start) or lte (End) operator, providing undesired flexibility and the option for the user to create a filter that would never return results, and B) Presented a logical comparison (And / Or) that we don't want.

Better Approach

A better approach was found on this StackOverflow question. This question has an answer by Matthew Erwin that gets us very close: it allows us to completely re-style the filter entirely, so we can present simply a Start Date input and an End date input. However, what I can't get working is associating the right filter operation with the right input (gte for the Start date, lte for the End date). My custom filter is as follows:

$scope.dateFilter = {
    extra: true,
    operators: {},
    ui: function (element) {
        var parent = element.parent();
        while (parent.children().length > 1)
            $(parent.children()[0]).remove();
 
        parent.prepend(
            "Start Date:<br/><span class=\"k-widget k-datepicker k-header\">" +
            "<span class=\"k-picker-wrap k-state-default\">" +
            "<input data-bind=\"value: filters[0].value\" class=\"k-input\" type=\"text\" data-role=\"datepicker\"" +
            " style=\"width: 100%\" role=\"textbox\" aria-haspopup=\"true\" aria-expanded=\"false\" aria-disabled=\"false\" " +
            " aria-readonly=\"false\" aria-label=\"Choose a date\">" +
            "<span unselectable=\"on\" class=\"k-select\" role=\"button\">" +
            "<span unselectable=\"on\" class=\"k-icon k-i-calendar\">select</span></span></span></span>" +
 
            "<br/>End Date:<br/>" +
            "<span class=\"k-widget k-datepicker k-header\"><span class=\"k-picker-wrap k-state-default\">" +
            "<input data-bind=\"value: filters[1].value\" class=\"k-input\" type=\"text\" data-role=\"datepicker\"" +
            " style=\"width: 100%\" role=\"textbox\" aria-haspopup=\"true\" aria-expanded=\"false\" " +
            " aria-disabled=\"false\" aria-readonly=\"false\" aria-label=\"Choose a date\">" +
            "<span unselectable=\"on\" class=\"k-select\" role=\"button\">" +
            "<span unselectable=\"on\" class=\"k-icon k-i-calendar\">select</span></span></span></span>"
        );
    }
};

With this approach, the Odata filter option is generated for each of the dates, however it uses the eq Equal To operator, so no values are ever returned. We aren't building filters specifically on the data source.Is there a simple way I can associate each of those date inputs with a specific filter operator? Is there a better way to approach this subject? It seems like filtering dates based on a Start - End range would be commonly desired.

Other Details

We are using AngularJS, and WebAPI with Odata.

21 Answers, 1 is accepted

Sort by
0
Mahlon
Top achievements
Rank 1
answered on 04 Aug 2014, 10:51 AM
Update: Since my last post I've tried to add a filter directly to my kendo data source. My reasoning goes that if I add the desired filters myself, I can specify what operator they use and use them in the grid filter UI.

So my Angular controller has code that basically works as follows:

$scope.dataSource = service.getDataSource();
 
var filter = {
    logic: "and",
    filters: [
        { field: "FinalDate", operator: "ge" },
        { field: "FinalDate", operator: "le" }
    ]
};
 
$scope.dataSource.filter(filter);

$scope.dataSource is what the grid is bound to with k-data-source. "FinalDate" is the field I want to filter on. 

However, when I try this I get the following error message: 

"Property not found!: Parameter 'FinalDate_0' not found in context"

It complains that it can't find the property FinalDate_0, but I didn't specify that - I specified 'FinalDate'. So what is going on?

Again, it seems like it should be much simpler to filter between two dates, so I can't help but feel that i am missing something and over-complicating matters.
0
Petur Subev
Telerik team
answered on 05 Aug 2014, 10:50 AM
Hello Mahlon,

Here is an example that shows how you can use the filterMenuInit event to customize the filter menu and set default operators. 

filterMenuInit: function(e){
                          if(e.field=="OrderDate"){
                            var operator = e.container
                                .find("[data-role=dropdownlist]:eq(2)").data("kendoDropDownList");
                            operator.value("lt");
                            operator.trigger("change");
                            e.container
                                .find("[data-role=dropdownlist]:eq(1)").data("kendoDropDownList").wrapper.hide();
                          }
                        },


Please notice that passing filters without values such as:

var filter = {
    logic: "and",
    filters: [
        { field: "FinalDate", operator: "ge" },
        { field: "FinalDate", operator: "le" }
    ]
};

Is not supported - you cannot set default operator in such way.

If this is not what you are searching for please elaborate.

Regards,
Petur Subev
Telerik
 

Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

 
0
Mahlon
Top achievements
Rank 1
answered on 05 Aug 2014, 04:42 PM
Thanks for the reply, Petur.

I created a method to use in the filterMenuinit method, but it doesn't seem to be firing. Here is the event markup for my grid:

<div id="grid"
  // Other properties
  k-on-filterMenuInit = "filterInit(kendoEvent)"

And here is the method in my Angular controller:

$scope.filterInit = function (e) {
    alert("Filter initialized");
        if (e.field == "FinalDate") {
            var beginOperator = e.container.find("[data-role=dropdownlist]:eq(0)").data("kendoDropDownList");
            beginOperator.value("gte");
            beginOperator.trigger("change");
             
            var endOperator = e.container.find("[data-role=dropdownlist]:eq(1)").data("kendoDropDownList");
            endOperator.value("lte");
            endOperator.trigger("change");
        }
    };

The alert statement is there just to verify that the function was called, but it never runs. Do you know what I might be doing wrong?
0
Petur Subev
Telerik team
answered on 06 Aug 2014, 08:19 AM
Hello again,

You should use dashes instead of camel case letters when the events and other options are more than one word. In this particular case you should use:

k-on-filter-menu-init = "filterInit(kendoEvent)"

Here is an example that I created:

http://dojo.telerik.com/@pesho/UMIw/2


Kind Regards,
Petur Subev
Telerik
 

Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

 
0
Mahlon
Top achievements
Rank 1
answered on 06 Aug 2014, 11:27 AM
Thanks Petur! That was exactly what I needed. With that, I've been able to get my date filter to look like the screenshot I included, which is very close to what I want. My only remaining questions are:

1.) Is there any way to change the text at the top of the filter? I'd like it to say "Show items with dates between:" instead of "Show items with value that:"

2.) Is there any way to prevent the user from changing the Logic operator, without hiding it? Since we're presenting them a date range "And" is the only sensible option.

Thanks again for all your help!
 







0
Mahlon
Top achievements
Rank 1
answered on 07 Aug 2014, 11:11 AM
I solved question number 1 above by using the "messages" configuration object in the column's filterable option, and that's working perfectly. Question 2, how to prevent the user changing the logic operator, still stands. 

And I have one (final) question: Is there any way to apply this filter menu initialization to any date field, instead of having to specify each individual field it applies to? So instead of:

if(e.field=="FieldName")

Having:
if(//Field type is Date)

That would be preferable so that all of our dates could be configured with one object, instead of having to build the filterMenuInit event handler for each grid for each field individually.
0
Accepted
Petur Subev
Telerik team
answered on 07 Aug 2014, 11:35 AM
Hello again,

Straight to the questions:

1) You can use the readonly method  of the Kendo DropDownList - you already know how to access it - the same way as accessing the other DropDownLists.

2) Inside the view event you have only access to the name of the field - you do not know the type. You can however get this information from the schema.model options.

Here is what I mean:


function onMenuInit(e) {
    alert('the type is -> ' + e.sender.dataSource.options.schema.model.fields[e.field].type);
}


e.g.

http://dojo.telerik.com/@pesho/UMIw/3

All the best,
Petur Subev
Telerik
 

Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

 
0
Mahlon
Top achievements
Rank 1
answered on 07 Aug 2014, 12:26 PM
Thanks Petur! That takes care of everything. :)

Thanks for the help!
0
Prasert
Top achievements
Rank 1
answered on 26 Jul 2015, 05:34 AM
Please tell me about how to make a filter two dates in the grid via razor (MVC).
0
Boyan Dimitrov
Telerik team
answered on 29 Jul 2015, 07:29 AM

Hello Prasert,

In order to modify the solution from my college Peter to work with Grid MVC please use the following configuration: 

    1. Configure the "Operators" option in the grid filterable option to set what operators can be used for dates (gte, lte) and what text is displayed for each (Begin Date, End Date); Use the "Extra" option of the column "filterable" option to get the extra Date selector in the filter menu;Use the "Messages" option of the column "filterable" option to customize the filter display message. 

.Filterable(ftb => ftb.Operators(oper => oper.ForDate(dat => dat.IsGreaterThanOrEqualTo("Begin Date").IsLessThanOrEqualTo("End Date"))).Extra(true).Messages(mes => mes.Info("Show items between dates")))

  2. Bind to the filter menu event and execute the same logic as the solution for Kendo UI Grid

.Events(e => e.FilterMenuInit("filterMenuInit"))

Regards,
Boyan Dimitrov
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
Prasert
Top achievements
Rank 1
answered on 30 Jul 2015, 10:32 AM

Thanks a lot Boyan Dimitrov.

You 're very cool!

0
Mark
Top achievements
Rank 1
answered on 25 Apr 2017, 03:20 PM

Looking at your dojo, this no longer works for order date, if you move to a new page of data, how to fix?

 

0
Boyan Dimitrov
Telerik team
answered on 27 Apr 2017, 11:36 AM

Hello Mark,

The communication in this thread has several replies with dojo examples. Could you please specify which dojo you are testing with and what are the expected behavior and the actual results? 

Regards,
Boyan Dimitrov
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 visualization (charts) and form elements.
0
Mark
Top achievements
Rank 1
answered on 27 Apr 2017, 12:07 PM

Hi Boyan,

Using Dojo: http://dojo.telerik.com/@pesho/UMIw/2

Initially I can click the "Order Date" filter menu and the options are set as desired (giving a between dates selector) , this is the behaviour I was expecting

Click on a different data page (i.e. go directly to page 5) and now click the "Order Date" filter menu and the options have reverted to both being "Is equal to" - this behaviour is undesirable because if you hide the operator selectors, they will only ever work on the first page after a reload.

 

Regards

Mark

 

0
Konstantin Dikov
Telerik team
answered on 01 May 2017, 08:45 AM
Hi Mark,

You could attach a handler for the "activate" event of the popup, which will fire each time the filter menu is opened:
Hope this helps.


Regards,
Konstantin Dikov
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 visualization (charts) and form elements.
0
Levan
Top achievements
Rank 1
answered on 15 May 2017, 12:54 PM

Hello,

Is there any directive for open event k-on-filter-menu-open? It does not work for me. 

0
Konstantin Dikov
Telerik team
answered on 17 May 2017, 06:41 AM
Hi Jaba,

You could define the event handler through the options of the Grid:
As for the directive, you could log this in our public repository, so we could expose this in the next releases:

Regards,
Konstantin Dikov
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 visualization (charts) and form elements.
0
Heiko
Top achievements
Rank 1
Iron
Veteran
answered on 09 Jan 2020, 10:15 AM

I know this is nearly 3 years old, but I ran into a similar problem (it concerns this example) 

When setting only the second filter value ("is before or equal to") and opening the filter menu again, the value moves from second to first filter value. Steps to reproduce:

1. open the filter menu on "Order Date" and enter "7/15/1996" for "Is before or equal to"
2. click in "Filter" (result: a filtered list with max. date 07/12/1996)
3. open the filter menu again - the date entered has moved to "Is after or equal to"

How can I prevent this?

Regards
Heiko

0
Alex Hajigeorgieva
Telerik team
answered on 13 Jan 2020, 09:02 AM

Hi, Heiko,

You can add a condition in the activate event of the FilterMenu popup to only change the operators if there is no active filter on the column. Here is the updated Dojo for your reference:

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

        $scope.filterInit = function (e) {       
          if (e.field == "OrderDate") {
            e.container.data("kendoPopup").bind("activate", function(e){
              if(!e.sender.options.anchor.hasClass("k-state-active")){
                var beginOperator = e.sender.element.find("[data-role=dropdownlist]:eq(0)").data("kendoDropDownList");
                beginOperator.value("gte");
                beginOperator.trigger("change");

                var endOperator = e.sender.element.find("[data-role=dropdownlist]:eq(2)").data("kendoDropDownList");
                endOperator.value("lte");
                endOperator.trigger("change");
              }
            });
          }
        };

Let us know what you think.

Kind Regards,
Alex Hajigeorgieva
Progress Telerik

Get quickly onboarded and successful with your Telerik UI for ASP.NET MVC with the dedicated Virtual Classroom technical training, available to all active customers.
0
Heiko
Top achievements
Rank 1
Iron
Veteran
answered on 13 Jan 2020, 09:56 AM

Hi Alex,

thanks for your reply. Unfortunately this is not a solution.

Let me describe the problem again: when you start entering a value in the second filter condition (in this case "is before or equal to"), then filter the grid and open the filter popup again, the entered value moves to the first filter condition; that is not correct, the entered value should remain in the second filter condition.

Kind regards
Heiko

0
Alex Hajigeorgieva
Telerik team
answered on 13 Jan 2020, 11:25 AM

Hi, Heiko,

Thank you for clarifying.

Programmatically, this is the expected behaviour for the reasons below:

  •  when the first filter has no value, it is ignored
  •  the second filter is pushed to the filter array and it goes to e.filter.filters[0]

This is the way the menu binds to - it uses the data source filters so it is expected that when there is no "second" filter, the second filter to become the first.

If you would like to keep the second filter second, then you need to push some default value to the first filter. For example, you could use the filter submit event. Here is the updated Dojo:

http://dojo.telerik.com/AnaLuGUt/3

var filterButton = e.container.find('button[type="submit"]');
      filterButton.click(function(){
        if(!firstDatePicker.value()){
             firstDatePicker.value(new Date(1,0,1));
             firstDatePicker.trigger("change");
             firstDropDown.value("gte");
             firstDropDown.trigger("change");
       }
});

Regards,
Alex Hajigeorgieva
Progress Telerik

Get quickly onboarded and successful with your Telerik UI for ASP.NET MVC with the dedicated Virtual Classroom technical training, available to all active customers.
Tags
Grid
Asked by
Mahlon
Top achievements
Rank 1
Answers by
Mahlon
Top achievements
Rank 1
Petur Subev
Telerik team
Prasert
Top achievements
Rank 1
Boyan Dimitrov
Telerik team
Mark
Top achievements
Rank 1
Konstantin Dikov
Telerik team
Levan
Top achievements
Rank 1
Heiko
Top achievements
Rank 1
Iron
Veteran
Alex Hajigeorgieva
Telerik team
Share this question
or