Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Backbone model .toJSON() doesn't render all attributes to JSON

I need to render a model's attributes to JSON so I can pass them into a template. Here is what a render() function for a view looks like:

render: function() {
  console.log(this.model);
  console.log(this.model.toJSON());
  $(this.el).html(this.template(this.model.toJSON()));
  return this;
},

Here is the attributes output after doing console.log(this.model):

created_at: "2012-04-19"
id: "29"
name: "item"
resource_uri: "/api/v1/item/29/"
updated_at: "2012-04-21"
user: "/api/v1/user/9/"

Here is the model's JSON output after doing console.log(this.model.toJSON()):

id: "29"
__proto__: Object

What happened?

Edit: Here is the instantiation:

  var goal = new Goal({id: id});
  goal.fetch();
  var goalFullView = new GoalFullView({
    model: goal,
  });

Here are the contents of the new view:

  console.log(this.model.attributes);
  console.log(this.model.toJSON());

Here is what the console says:

Object
created_at: "2012-04-23"
id: "32"
name: "test"
resource_uri: "/api/v1/goal/32/"
updated_at: "2012-04-23"
user: "/api/v1/user/9/"
__proto__: Object

Object
id: "32"
name: "test"
__proto__: Object

If the toJSON is supposed to make a clone of the attributes, why doesn't it copy the correct name or why doesn't it copy the created_at, updated_at fields?

Edit 2: Here is the model:

  var Goal = Backbone.Model.extend({

    // Default attributes for Goal
    defaults: {
      name: "empty goal",
    },

    // Check that the user entered a goal
    validate: function(attrs) {
      if (!attrs.name) {
        return "name is blank";
      }
    },

    // Do HTTP requests on this endpoint
    url: function() {
      if (this.isNew()) {
        return API_URL + "goal/" + this.get("id") + FORMAT_JSON;
      }
      return API_URL + "goal/" + FORMAT_JSON;
      //API_URL + "goal" + FORMAT_JSON, 
    },
  });

Edit 3: I figured out that I need to use the success callback from fetch to render a view that uses the model:

goal.fetch({success: function(model) { var goalFullView = new GoalFullView({ model: goal, }); }});

like image 881
egidra Avatar asked Apr 21 '12 19:04

egidra


1 Answers

The toJSON() method just returns a shallow clone of the model's attributes property.

From the annotated Backbone.js source:

toJSON: function(options) {
  return _.clone(this.attributes);
}

Without seeing more of your code, it looks like you directly set properties on the model object, rather than using the set function to set model attributes.

I.e. don't do this:

model.name = "item";

do this:

model.set("name", "item");

EDIT:

For your specific issue, it's possible that you called toJSON before the model had finished loading from the server.

E.g. This won't always work as expected:

var model = new Goal({id: 123});
model.fetch();
console.log(model.toJSON());

But this will:

var model = new Goal({id: 123});
model.fetch({
  success: function() {
    console.log(model.toJSON());
  }
});
like image 144
jimr Avatar answered Nov 12 '22 04:11

jimr