简体   繁体   中英

Display Kendo Grid column as DateTime but ignore Time when filtering

I have a Kendo Grid and a column "Sale Time" displayed as MM/dd/yyyy HH:mm a (1/3/2015 2:34 PM).

Now I want to be able to filter by Date only, ignoring the Time. But by default, the filter is looking at Time, so any date I filter using "Is Equal To" returns no results.

Here's a JSFiddle I made to illustrate the issue: http://jsfiddle.net/dmathisen/yx7huvxp/

And some code so I can post the jsfiddle link :)

columns: [
    { field: "ModelName", title: "Model" },
    { field: "DefaultMonoCPP", title: "Mono Cost" },
    { field: "SaleTime", title: "Sale Time", format: "{0:g}" }
]

You can define a schema.parse function that generates an additional field called SaleDate that contains only the Date part of the SaleTime .

Then, when showing the columns in the grid, you use this.

Something like:

// Schema definition
schema: {
    model: {
        id: "ModelID",
        fields: {
            ModelName: { type: "string" },
            DefaultMonoCPP: { type: "number" },
            SaleTime: { type: "date" },
            SaleDate: { type: "date" }  // Additional field with the `Date` of `SaleTime`
        }
    },
    parse: function(d) {
        $.each(d, function(idx, elem) {
            // Compute SaleDate from SaleTime
            elem.SaleDate = kendo.parseDate(elem.SaleTime, "MM/dd/yyyy");
        });
        return d;
    }        
}

// Columns definition
columns: [
    {
        field: "ModelName",
        title: "Model"
    },
    {
        field: "DefaultMonoCPP",
        title: "Mono Cost"
    },
    {
        field: "SaleDate",
        title: "Sale Time",
        template: "#= kendo.toString(SaleTime, 'g') #"
    }
],

Your JSFiddle modified here: http://jsfiddle.net/OnaBai/yx7huvxp/10/

Telerik does not support this out of the box. See here and here , and this guy did a brilliant server side solution using a logical datetime filter transformation. However, personally I always found it weird to go to server side for client side matters.

So in the end I usually just split the date and time parts into two different columns, OR used datetime without offering the filter option, OR avoided datetime fields if possible in the design.

I also have a working datasource hack, but... I don't recommend using it. If you're interested though, here it is...


Basically the idea is to duplicate the data column, one is with full date, the other one with only date and no time. Then on the column UI, you want to show the full date, but for underlying data source, you want to use the fake date. The user always sees the full date, but the filters will use the timeless date.

Here is a demo .

RandDate is my full date. RandDate2 is my fake partial date without time.

RandDate: Mon Apr 07 2014 06:15:00 GMT-0400 (Eastern Daylight Time)
RandDate2: Mon Apr 07 2014 00:00:00 GMT-0400 (Eastern Daylight Time)

In my column definition, I use the partial date as the field, but display the full date with a template

{
    field: "RandDate2", //Set column source to the fake one without time
    title: "Random Date",
    template: "#= kendo.toString(RandDate,'g') #", //display the full date and time
}

I'm using SharePoint 2010 REST Service as datasource, this did the job for me: ("magic" happens in the parameterMap part)

 $scope.mainGridOptions = { ... dataSource: new kendo.data.DataSource({ type: "odata", transport: { read: { url: $scope.filterParams.url, dataType: "json" }, parameterMap: function (options, type) { if (options && options.filter && options.filter.filters && options.filter.filters.count != 0) { options.filter.filters.forEach(function (f) { if (f.operator && f.operator == 'eq' && f.value && typeof f.value.getMonth == 'function' && typeof f.value.getMonth() == 'number') { f.operator = 'gt'; var newFilter = { field: f.field, operator: 'lt', value: new Date(f.value.getFullYear(), f.value.getMonth(), f.value.getDate(), 23, 59, 59) }; options.filter.filters.push(newFilter); } }) } var params = kendo.data.transports.odata.parameterMap(options, type); delete params.$format; return params; } }, ... } 

what it basically does: if some filter is applied, check if operator is 'eq' (equals) and if the value is a date. since typeof f.value is an object and f.value instanceof Date is always true, even if you say something like f.value = new Date('foo') , checking if the value object has a function 'getMonth' that returns a number seems legit to validate that f.value is a date. the function then changes the 'eq' operator to 'gt'. (note that f.value's time is 00:00:00!). after that it creates a new filter with 'lt' operator, same date but another time (23:59:59 in my case) and pushes it to the filters array. since sharepoint has some problems with that '$format' property, we delete it.

so ' date gt 19.10.2015 00:00:00 and date lt 19:10:2015 23:59:59 ' is basically the same as ' date eq 19.10.2015 '

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM