3

I'm using KnockoutJS with the mapping plugin and all is working well, apart from a DateTime field which is serialized as ticks like so: /Date(x)/ where x = ticks.

How would I: 1) Parse the date object into human readable form? 2) Return this out from the custom binding back into the value in the model?

rae1
  • 6,066
  • 4
  • 27
  • 48
jaffa
  • 26,770
  • 50
  • 178
  • 289
  • Did you read this: http://stackoverflow.com/questions/5942789/in-knockoutjs-does-ko-tojson-work-with-dates – mplungjan May 10 '11 at 18:22
  • Yes, not sure how it would help me though. I'm wondering whether to format the date as a string represented in the model. Thoughts? – jaffa May 11 '11 at 15:11

3 Answers3

14

Here's an example of a custom binding in knockoutjs. It uses moment.js to parse the date

  ko.bindingHandlers.date = {
    update: function (element, valueAccessor) {
      var value = valueAccessor();
      var date = moment(value);
      $(element).text(date.format("L"));
    }
  };

In your javascript you can then use the new binding like any other knockout binding.

  <td data-bind="date:Created" />
Mike Ward
  • 3,211
  • 1
  • 29
  • 42
  • I'd recommend a minor change: If the incoming element is an instance of HTMLInputElement, set the element's val property. There's probably a bug lurking in there somewhere, but it works so far. – Corey Cole Sep 18 '12 at 05:59
  • 2
    this gives me 'NaN' unless you change the *var date = moment(value)* call to instead be *var date = moment(value())* as in ekenman's answer – nvuono Apr 24 '13 at 22:25
5

I don't know anything about KnockoutJS, so there may be a better way of doing this that's already built-in. I also don't know anything about the second question. Hopefully someone who actually knows something about it can help you.

So, with that disclaimer, here's how you can convert it using "plain" JavaScript (you might need to include Douglas Crockford's json2.js if you want to support "old" browsers). JSON.parse takes an optional reviver argument that can replace each value as it's parsed.

JSON.parse(jsonText, function(key, value) {
    // Check for the /Date(x)/ pattern
    var match = /\/Date\((-?\d+)\)\//.exec(value);
    if (match) {
        var date = new Date(+match[1]); // Convert the ticks to a Date object
        return humanReadable(date); // Format the date how you want it
    }

    // Not a date, so return the original value
    return value;
});
Matthew Crumley
  • 101,441
  • 24
  • 103
  • 129
  • Thanks for the suggestion - for any knockoutJS experts how do I ensure the Knockout binding function returns the converted date back to the template? – jaffa May 11 '11 at 15:12
  • 1
    In the end I decided to just use string formatting on the model side which is much easier than converting the date. See this link: http://encosia.com/2009/04/27/how-i-handle-json-dates-returned-by-aspnet-ajax/ – jaffa May 17 '11 at 12:30
  • Regex probably needs to be updated. This doesn't correctly handle dates prior to 1-1-1970 since the ticks will be negative. – hawkke Jul 10 '14 at 21:39
2

Here is an example if you have functions in your viewmodel and binding to an input:

ko.bindingHandlers.date = {
        update: function (element, valueAccessor) {
            var value = valueAccessor();
            var date = moment(value());
            var strDate = date.format('YYYY-MM-DD');
            $(element).val(strDate);
        }
    };

Link to moment.js

ekenman
  • 995
  • 1
  • 13
  • 29