0

I am using Knockout.js integration with Kendo UI Grid (http://rniemeyer.github.io/knockout-kendo/web/Grid.html).

In my JSON I am returning a date which shows up as Oct 06 2015, 03:54 PM -04:00.

I have specified the column type and the format as format: "{0:MM/dd/yyyy HH:mm tt}" but it seems it is getting completely ignored.

The following is the kendogrid binding definition:

<div data-bind="kendoGrid: {
  data: projectSubmissions,
  dataSource: {
    schema: {
      model: {
        fields: {
          SubmissionId: { type: 'number' } ,
          FormName: { type: 'string' } ,
          IdVersion: { type: 'string' },
          SubmittedDateFormatted: { type: 'string'},
          SubmittedDate: { type: 'date'},
        }
      }
    }
  },
  groupable: false,
  scrollable: false,
  filterable: {
    extra: false,
    operators: {
      string: {
          startswith: 'Starts with',
          eq: 'Is equal to',
          neq: 'Is not equal to'
      }
    }
  },
  sortable: true,
  pageable: { pageSize: 10 },
  columns: [
    {
      field: 'SubmissionId',
      title: 'No.',
      width: 70,
    }
    ,{ field: 'FormName', title: 'Form', width:120 }
    ,{ field: 'IdVersion', title: 'Id/Version', width:100}
    ,{
      field: 'SubmittedDate',
      filterable: true,
      title: 'Submitted Date',
      format: '{0:MM/dd/yyyy HH:mm tt}',
      width: 120
    }
    ,{ field: 'Inspector', title: 'Inspector', filterable: true, width:140 }
    ,{ field: 'CellNo', title: 'Cell No.', width:100, filterable: false }
  ]
}"></div>
Tomalak
  • 332,285
  • 67
  • 532
  • 628
David
  • 3,047
  • 4
  • 45
  • 79
  • There is a typo in your code: `''{0:MM/dd/yyyy HH:mm tt}'`, you're using two quotations before using the format. – Buzinas Oct 07 '15 at 12:08
  • Thanks - i fixed (that was just an error when pasting sample) – David Oct 07 '15 at 12:11
  • How do you parse your json? – Amit Oct 07 '15 at 12:17
  • I am using ko.mapping.fromJS(data, {}, this); to perform the mapping. The resultant property looks like "SubmittedDate": "2015-10-06T15:54:02.047", – David Oct 07 '15 at 12:19
  • I also cannot get the filter UI:datepicker to work either, I am hoping these issues can be resolved – David Oct 07 '15 at 12:21

2 Answers2

3

Your problem is not with the format setting. This controls how to format a value for display. Your problem is with the value itself. For the format to succeed, the value needs to be a Date object to begin with, and as it is now, it's a string.

You could use a mapping object (as shown here) to create a Date object during the mapping process:

var mapping = {
  SubmittedDate: {
    create: function(options) {
              return new Date(options.data);
    }
};
ko.mapping.fromJS(data, mapping, this);
Amit
  • 45,440
  • 9
  • 78
  • 110
  • This solved my problem, thank you. I have similar issue with filterable ui:datepicker with knockout kendo grid as well http://stackoverflow.com/questions/32994344/knockout-kendo-js-grid-uidatepicker-filter – David Oct 07 '15 at 14:04
1

The root problem is that the JSON spec defines no Date data type. Since there is no standard, all kinds of string formats are being used to represent dates in JSON documents. The Kendo Grid however expects Date objects, not strings.

In your case it appears as if the server sends "Oct 06 2015, 03:54 PM -04:00", which is actually one of the formats that Date.parse() would accept.

JavaScript's JSON.parse() function mitigates this omission in the standard by accepting a reviver function that can convert any special values in your JSON according to your rules. This is commonly used to "revive" dates.

Adapted to your input JSON:

function reviveDates(key, val) {
    if ( key === "SubmittedDate" ) {
        return new Date(val);
    }
    return val;
}

and

JSON.parse(yourJSON, reviveDates);

To make this more convenient you can actually integrate that into jQuery's low-level Ajax routines so that you don't have to deal with date conversion at the higher level at all:

$.ajaxSetup({
    converters: {
        'text json': function (data) {
            try {
                return JSON.parse(data, reviveDates);
            } catch (ex) {
                $.error("Invalid JSON: " + data);
            }
        }
    }
});
Tomalak
  • 332,285
  • 67
  • 532
  • 628
  • This looks quite interesting as well, i tried to add but something is not quite right. In the above sample what is reviveDates ...something incorrect there? thx – David Oct 07 '15 at 14:03
  • @David `reviveDates` is a function that I define in my fist code sample. – Tomalak Oct 07 '15 at 14:06
  • The advantage of using this approach is that it's located in the jQuery core, any and all dates you receive will get their dates converted automatically. You will never have to care again in knockout. It's as if the server would send actual dates. You can of course also use it to preprocess any other JSON data you receive. – Tomalak Oct 07 '15 at 14:12
  • It is at the core level which is good, however you still are specifying a function for each set of data that comes back via json ..i.e. reviveDates function. I initially thought great it would apply to all dates and it would magically figure out which fields were date, but unfortunately for each json request i would have to have a function for those date fields to parse. Is there a way to make revivedates generic for any date fields? – David Oct 07 '15 at 14:17
  • @David Just adapt the function. My sample function uses an `if (key === "SubmittedDate")` check. All you need to do is to make that check more generic so that it applies to all date fields you receive. You don't need to create a special function for each JSON request. This solution is meant to be executed exactly *one time* at page load. – Tomalak Oct 07 '15 at 14:28