We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date
close icon

How to use DateRangePicker on custom menu filter UI


Hi,

Im using ODataV4Adaptor and remote datasource, and I have a date column where I need to use the Menu Filter, but instead of the default Date Picker, I need to use the DateRangePicker, so I have the below function:

function onDataBoundMainGrid(args) {
var dateTimePickerObj = new ej.calendars.DateRangePicker({
floatLabelType: 'Never'
});
this.columns[1].filter.ui = {
create: (args) => {
elem = document.createElement('input');
args.target.appendChild(elem);
dateTimePickerObj.appendTo(elem);
},
read: (args) => {
args.fltrObj.filterByColumn(args.column.field, args.operator, dateTimePickerObj.value);
},
write: (args) => {
dateTimePickerObj.value = args.filteredValue;
}
}
}

The date range picker gets rendered correctly, but once I do click on the "Apply" button, I get this error:



And this the column of my grid:

<e-grid-column type="datetime" field="StartDt"></e-grid-column>

I also tried:
<e-grid-column type="date" field="StartDt"></e-grid-column>

but I got the same error.

Is there a way to achieve this functionality?

Thanks!

9 Replies

RR Rajapandi Ravi Syncfusion Team December 7, 2020 12:11 PM UTC

Hi Rony, 

Greetings from syncfusion support 

Based on your query we have prepared a sample and render a dateRangePicker as custom component in filter menu and try to reproduce the issue. But its working fine from our end. For your convenience we have attached the sample. so please refer the below sample and video demo for more information. 
 

<ejs-grid id="Grid" allowFiltering="true" height="500" actionBegin="begin" dataBound="bound" load="load" toolbar="@(new List<string>() { "Add", "Edit", "Delete", "Update", "Cancel" })" allowPaging="true"> 
        <e-grid-editSettings allowAdding="true" showDeleteConfirmDialog="true" allowDeleting="true" allowEditing="true" mode="Normal"></e-grid-editSettings> 
        <e-grid-pagesettings pageSize="8"></e-grid-pagesettings> 
        <e-grid-filterSettings type="Menu"></e-grid-filterSettings> 
        <e-grid-columns> 
            .  .  .  .  .  .  . 
       </e-grid-columns> 
    </ejs-grid> 
 
<script> 
    function load () { 
        var grid = document.getElementsByClassName('e-grid')[0].ej2_instances[0]; 
        grid.dataSource = new ej.data.DataManager({ 
            adaptor: new ej.data.ODataV4Adaptor 
        }); 
    } 
 
    function begin(args) {  //actionBegin event 
        if (args.requestType === "filtering" && args.currentFilteringColumn === "OrderDate") { 
            var grid = document.getElementsByClassName('e-grid')[0].ej2_instances[0]; 
            var daterange = document.getElementsByClassName('e-daterangepicker')[0].ej2_instances[0]; 
            // End date value is added as additional filter value with ‘lessthan’ filter operator 
            args.columns.push({ 
                actualFilterValue: {}, 
                actualOperator: {}, 
                field: "OrderDate", 
                ignoreAccent: false, 
                isForeignKey: false, 
                matchCase: false, 
                operator: "lessthan", 
                predicate: "and", 
                uid: grid.getColumnByField(args.currentFilteringColumn).uid, 
                value: daterange.value[1] 
            }); 
        } 
    } 
 
    function bound() {  
        this.columns[3].filter.ui = { 
            create: (args) => { 
                elem = document.createElement('input'); 
                args.target.appendChild(elem); 
                var isFiltered = args.target.classList.contains("e-filtered"); 
                //var daterange = document.getElementsByClassName('e-daterangepicker')[0].ej2_instances[0]; 
                dateTimePickerObj = new ej.calendars.DateRangePicker({ 
                    floatLabelType: 'Never', 
                    change: function (args) { 
                        if (args.value) { 
                            var datevalue = args.value; 
                            var grid = document.getElementsByClassName('e-grid')[0].ej2_instances[0]; 
                            grid.filterByColumn("OrderDate", "greaterthanorequal", datevalue[0]); 
 
                        } 
                    } 
                }); 
                dateTimePickerObj.appendTo(elem); 
            } 
       }  
    } 
</script> 





Regards, 
Rajapandi R


RD Rony De Sousa December 11, 2020 08:13 PM UTC


Hi Rajapandi,

Somehow I didn't see your response before. Thanks for our help and apologies for my delayed response.

I'll review your sample and get back to you in case of any queries.

Regards!


RR Rajapandi Ravi Syncfusion Team December 14, 2020 05:31 AM UTC

Hi Rony, 

Thanks for the update 

We will wait to hear from you. 

Regards, 
Rajapandi R 



RR Rajapandi Ravi Syncfusion Team December 17, 2020 12:08 PM UTC

Hi Emiliano, 

We are happy to hear that you have founded the solution at your end. 

Please get back to us if you need further assistance. 

Regards, 
Rajapandi R 




EM Emiliano December 17, 2020 12:30 PM UTC

I would like to share a piece of code to help Rony De Sousa and others who want to make a date range filter easily in a grid and are having dificulties.

I think that the Rajapandi Ravi answer have some problems:
After you have selected a date range, it doesn't show the selected data range anywhere. If you open again the same DateRangePicker you can't see the selected date interval. And i think that's not helpfull, because the person can't see if the dates are correct or not.
Another one is everytime i have a grid with a date column, and if i want to create a date range filter, i have to create the 'actionbegin'and 'databound' events and create code for a column, which the index is hardcoded with a number. If later i add another column before the date column one, i have to correct the column index.

I have developed some code wich corrects this two problems, and works with persistance enabled and with default columns filters in filterSettings, but it uses the FilterBar mode in the Grid.
There's only one problem, that i will ask Syncfusion support to correct, that is in the FilterBarStatus, the message is not correct, but everything works as supposed to.
I use this code in Grids with URL Adaptor, and in MVC and it works. I tried it in the sample Rajapandi Ravi give, and it works ok.

Put this custom component functions in a shared javascript file:
(I put this code in a javascript file in _Layout file, so i can access it in every grid i want)

function createFilterDateRangePicker(args) {
        var element = document.createElement('input');
        element.id = args.column.field;
        return element;
    }

    function readFilterDateRangePicker(args) {
        return this.filterSettings.columns.filter(col => col.field == this.column.field).map(col => col.value);
    }

    function writeFilterDateRangePicker(args) {
        var datePicker = new ej.calendars.DateRangePicker({
            startDate: this.parent.filterSettings.columns.filter(col => col.field == args.column.field && col.operator == 'greaterthanorequal').map(col => col.value) ?? null,
            endDate: this.parent.filterSettings.columns.filter(col => col.field == args.column.field && col.operator == 'lessthan').map(col => col.value) ?? null,
            focus: function () { this.show(); },
            change: function (args) {
                let grid = this.element.closest(".e-grid").ej2_instances[0];
                if (args.value) {
                    let predicate = grid.filterSettings.columns.filter(function (obj) { return obj.field !== args.element.id; });
                    predicate.push(
                        {
                            actualFilterValue: {},
                            actualOperator: {},
                            field: args.element.id,
                            ignoreAccent: false,
                            isForeignKey: false,
                            matchCase: false,
                            operator: "greaterthanorequal",
                            predicate: "and",
                            uid: grid.getColumnByField(args.element.id).uid,
                            value: args.value[0]
                        },
                        {
                            actualFilterValue: {},
                            actualOperator: {},
                            field: args.element.id,
                            ignoreAccent: false,
                            isForeignKey: false,
                            matchCase: false,
                            operator: "lessthan",
                            predicate: "and",
                            uid: grid.getColumnByField(args.element.id).uid,
                            value: args.value[1]
                        }
                    );
                    grid.filterSettings.columns = predicate;
                }
                else
                    grid.removeFilteredColsByField(args.element.id);
            },
            cleared: function (args) {
                let grid = this.element.closest(".e-grid").ej2_instances[0];
                grid.removeFilteredColsByField(this.element.id);
            }
        });
        datePicker.appendTo(args.element);
    }

So the user only needs to put this one line code in the column of the grid, IN ANY GRID in your application:

Core:
filterBarTemplate=@(new { create = "createFilterDateRangePicker", read = "readFilterDateRangePicker", write = "writeFilterDateRangePicker" })
MVC:
.FilterBarTemplate(new { create = "createFilterDateRangePicker", read = "readFilterDateRangePicker", write = "writeFilterDateRangePicker" })

It will be like this:

I would like to thank Syncfusion for their support.


EM Emiliano replied to Rajapandi Ravi December 17, 2020 02:19 PM UTC

Hi Emiliano, 

We are happy to hear that you have founded the solution at your end. 

Please get back to us if you need further assistance. 

Regards, 
Rajapandi R 



I had to correct the code in the 'readFilterDateRangePicker' event, for the column filter work ok with manual input of the range date.
But now i have a little problem that is when i insert manually the text of the dates, the filter and the grid works ok but i receive an error:



Thanks


RR Rajapandi Ravi Syncfusion Team December 23, 2020 11:53 AM UTC

Hi Emiliano, 

We have analyzed your query and we could see that you are facing a console error when enter the text manually. Based on your query we have prepared a sample and we suggest you to follow the below way to achieve your requirement. Please refer the below code example and sample for more information. 

 
<ejs-grid id="Grid" allowPaging="true" load="onLoad" actionBegin="begin" allowFiltering="true" toolbar="@(new List<string>() {"Add", "Edit", "Update", "Delete" })"> 
    <e-data-manager url="/Home/UrlDataSource" adaptor="UrlAdaptor" insertUrl="/Home/Insert" updateUrl="/Home/Update" removeUrl="/Home/Remove"></e-data-manager> 
 
    <e-grid-editSettings allowAdding="true" allowDeleting="true" allowEditing="true" mode="Normal"></e-grid-editSettings> 
 
    <e-grid-columns> 
        .  .  .  .  .  .  .  . 
       <e-grid-column field="OrderDate" filterBarTemplate="filterBarTemplate" headerText="Order Date" format="yMd" type="date" width="170"></e-grid-column> 
        .  .  .  .  .  .  .  .  
    </e-grid-columns> 
</ejs-grid> 
<script> 
    var secval; 
    var flag = true; 
    function onLoad() { 
        this.dataSource.dataSource.headers = [{ 'XSRF-TOKEN': $("input:hidden[name='__RequestVerificationToken']").val() }]; 
    } 
 
    function createFilterDateRangePicker(args) { 
        var element = document.createElement('input'); 
        element.id = args.column.field; 
        return element; 
   } 
 
    function begin(args) { //push the 2nd date value in to the columns 
        if (args.requestType === "filtering" && args.currentFilteringColumn === "OrderDate") { 
            if (args.columns[0]) { 
                args.columns[0].properties.operator = "greaterthanorequal"; //maintain the 1st date column operator value as “greaterthanorequal” 
            } 
            args.columns.push({ 
                actualFilterValue: {}, 
                actualOperator: {}, 
                field: "OrderDate", 
                ignoreAccent: false, 
                isForeignKey: false, 
                matchCase: false, 
                operator: "lessthan", 
                predicate: "and", 
                uid: this.getColumnByField( 
                    args.currentFilteringColumn 
                ).uid, 
                value: secval 
            }); 
        } 
    } 
 
    function readFilterDateRangePicker(args) { 
        var grid = document.getElementsByClassName('e-grid')[0].ej2_instances[0]; 
        return  args.querySelector('input').ej2_instances[0].value[0].toLocaleDateString();//return the 1st date value as string format 
    } 
 
    function writeFilterDateRangePicker(args) { 
        var datePicker = new ej.calendars.DateRangePicker({ 
           change: function (args) { 
                    let grid = this.element.closest(".e-grid").ej2_instances[0]; 
                    if (args.value) { 
                        secval = args.value[1]; 
                        grid.filterByColumn("OrderDate", "greaterthanorequal",args.value[0]); //filter the 1st date value 
                    } 
                    else 
                        grid.removeFilteredColsByField(args.element.id); 
                 
            }, 
            cleared: function (args) { 
                let grid = this.element.closest(".e-grid").ej2_instances[0]; 
                grid.removeFilteredColsByField(this.element.id); 
            } 
        }); 
        datePicker.appendTo(args.element); 
    }; 
 
</script> 
 
 


Regards, 
Rajapandi R 



EM Emiliano January 4, 2021 12:35 PM UTC

The solution you provide, does not work for me, because it NEEDS the actionbegin event where you put a hardcoded column filter, and i developed a solution where i only need to put a SINGLE LINE, in ANY grid and it will work. But when Filter.js try to scan the value, it gives an error because it's not expecting a array with 2 date values.

The sample you provide have the same problem than in this ticket.


RR Rajapandi Ravi Syncfusion Team January 5, 2021 11:52 AM UTC

Hi Emiliano, 

Thanks for the update 

By default in EJ2 Grid, when we filter the date column it will set the operator as equal and filtered the dates values easily. This is the default behavior of date filtering with equal operator.  

When you enter the text manually and hit enter it will triggers the read method. In this read method you should return only the First date value as string format and you should change the first date value operator to “greaterthanorequal” in actionBegin event of Grid. Otherwise it will consider the operator as “equal”. Then you should push the second date value in columns in actionBegin event. Since this was a template, we have to customize by using this workaround and achieve the requirement. Please refer the below video demo and sample for more information. 


 
<ejs-grid id="Grid" allowPaging="true" load="onLoad" actionBegin="begin" allowFiltering="true" toolbar="@(new List<string>() {"Add", "Edit", "Update", "Delete" })"> 
    <e-data-manager url="/Home/UrlDataSource" adaptor="UrlAdaptor" insertUrl="/Home/Insert" updateUrl="/Home/Update" removeUrl="/Home/Remove"></e-data-manager> 
 
    <e-grid-editSettings allowAdding="true" allowDeleting="true" allowEditing="true" mode="Normal"></e-grid-editSettings> 
 
    <e-grid-columns> 
        .  .  .  .  .  .  .  . 
       <e-grid-column field="OrderDate" filterBarTemplate="filterBarTemplate" headerText="Order Date" format="yMd" type="date" width="170"></e-grid-column> 
        .  .  .  .  .  .  .  .  
    </e-grid-columns> 
</ejs-grid> 
<script> 
    var secval; 
    var flag = true; 
    function onLoad() { 
        this.dataSource.dataSource.headers = [{ 'XSRF-TOKEN': $("input:hidden[name='__RequestVerificationToken']").val() }]; 
    } 
 
    function createFilterDateRangePicker(args) { 
        var element = document.createElement('input'); 
        element.id = args.column.field; 
        return element; 
   } 
 
    function begin(args) { //push the 2nd date value in to the columns 
        if (args.requestType === "filtering" && args.currentFilteringColumn === "OrderDate") { 
            if (args.columns[0]) { 
                args.columns[0].properties.operator = "greaterthanorequal"; //maintain the 1st date column operator value as “greaterthanorequal” instead of equal 
            } 
            args.columns.push({ 
                actualFilterValue: {}, 
                actualOperator: {}, 
                field: "OrderDate", 
                ignoreAccent: false, 
                isForeignKey: false, 
                matchCase: false, 
                operator: "lessthan", 
                predicate: "and", 
                uid: this.getColumnByField( 
                    args.currentFilteringColumn 
                ).uid, 
                value: secval 
            }); 
        } 
    } 
 
    function readFilterDateRangePicker(args) { 
        var grid = document.getElementsByClassName('e-grid')[0].ej2_instances[0]; 
        return  args.querySelector('input').ej2_instances[0].value[0].toLocaleDateString();//return the 1st date value as string format 
    } 
 
    function writeFilterDateRangePicker(args) { 
        var datePicker = new ej.calendars.DateRangePicker({ 
           change: function (args) { 
                    let grid = this.element.closest(".e-grid").ej2_instances[0]; 
                    if (args.value) { 
                        secval = args.value[1]; 
                        grid.filterByColumn("OrderDate", "greaterthanorequal",args.value[0]); //filter the 1st date value 
                    } 
                    else 
                        grid.removeFilteredColsByField(args.element.id); 
                 
            }, 
            cleared: function (args) { 
                let grid = this.element.closest(".e-grid").ej2_instances[0]; 
                grid.removeFilteredColsByField(this.element.id); 
            } 
        }); 
        datePicker.appendTo(args.element); 
    }; 
 
</script> 
 
 



Regards, 
Rajapandi R

Loader.
Live Chat Icon For mobile
Up arrow icon