0

I've been messing with the ember.js todoMVC example. Got it done and working just fine, but to learn some more I started modifying it.

I updated the model from this:

Todos.Todo = DS.Model.extend({
   title: DS.attr('string'),
   isCompleted: DS.attr('boolean'),
});

to this:

Todos.Todo = DS.Model.extend({
    title: DS.attr('string'),
    isCompleted: DS.attr('boolean'),
    date: DS.attr('date')
}); 

(I'm using ember-data as well).

Added to the template to be able to enter a date and then updated the controller action for createTodo to this:

actions: {
    createTodo: function(){
        var title = this.get('newTitle');
        var date = this.get('newDate');     

        if(!title.trim()){
            return;
        }

        var todo = this.store.createRecord('todo',{
            date: date,
            title: title,
            isCompleted: false              
        });

        //this clears the input field value
        this.set('newTitle', '');
        this.set('newDate', '');

        //and save the instance of the model.
        todo.save();
    },
//...More code

Great, all works, so then I'm saving it to localstorage using the localstorage adapter.

This is where things break, the date is not being saved to localstorage, and its because of the toJSON and serialize method which are used in the adapter.

Specifically the adapter does this:

    _addRecordToNamespace: function (namespace, record) {
            var data = record.serialize({includeId: true});
            namespace.records[data.id] = data;
    }

Which takes the _data sub-object that is part of the record, and which looks like so:

//taken from the chrome inspector 
_data: Object
  __ember1386208719445_meta: Meta
  date: "12/11/2013"
  isCompleted: false
  title: "testing something"
  __proto__: Object

and returns:

Object {title: "testing something", isCompleted: false, date: null}

toJSON returns the same thing.

SO TLDR && Question:

Why do the methods toJSON and serialize set my date to null, when it clearly has a value, and that value is a string?

Ryan
  • 5,644
  • 3
  • 38
  • 66

2 Answers2

1

It's because you said it was of type date, but you were setting it as a string, so when ember data tried to serialize it it was confused because it expected a date, so it would return null.

serialize: function(date) {
  if (date instanceof Date) {
    var days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
    var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];

    var pad = function(num) {
      return num < 10 ? "0"+num : ""+num;
    };

    var utcYear = date.getUTCFullYear(),
      utcMonth = date.getUTCMonth(),
      utcDayOfMonth = date.getUTCDate(),
      utcDay = date.getUTCDay(),
      utcHours = date.getUTCHours(),
      utcMinutes = date.getUTCMinutes(),
      utcSeconds = date.getUTCSeconds();


    var dayOfWeek = days[utcDay];
    var dayOfMonth = pad(utcDayOfMonth);
    var month = months[utcMonth];

    return dayOfWeek + ", " + dayOfMonth + " " + month + " " + utcYear + " " +
         pad(utcHours) + ":" + pad(utcMinutes) + ":" + pad(utcSeconds) + " GMT";
  } else {
    return null;
  }
}
Kingpin2k
  • 47,277
  • 10
  • 78
  • 96
  • Yea, once I saw that taking the `date` type out of the `DS.attr()` fixed it, I went and looked at the source for ember-data and saw what you posted. – Ryan Dec 05 '13 at 03:36
-1

Your date format is not valid. Try "2013-02-07T16:44:57" instead of "12/11/2013".

chopper
  • 6,649
  • 7
  • 36
  • 53
  • 1
    The format doesn't matter. It's a string. But for thoroughness sake, I tried what you suggested, and it didn't fix the problem. – Ryan Dec 05 '13 at 02:45
  • Yes it's a string, but your DS.attr specifies it as a date, so it expects a certain format. Try the edit to my answer. – chopper Dec 05 '13 at 02:55
  • That's good to know about the DS.attr, but I don't think that's the issue. If I look at the record in the ember inspector, the date is there, its only when I refresh the page, and it has to retrieve the record from the adapter, that the date is no longer there. And I can repeat the error by assigning the record to the window object, and then in the chrome inspector calling `serialize()` or `toJSON()` on it. – Ryan Dec 05 '13 at 03:03
  • Any chance you could put together a jsBin? – chopper Dec 05 '13 at 03:21
  • Your last comment, got me thinking, I removed the 'date' type specification from `DS.attr()` and now it works. – Ryan Dec 05 '13 at 03:26
  • Great. Since you're returning it as a string, that should be equivalent of specifying it as a DS.attr('string'). If you're not doing any date manipulation you should be set (and even then you could convert it into the JS date format). – chopper Dec 05 '13 at 03:30