Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Backbone.js fetch not actually setting attributes

I have a basic backbone model, its urlRoot attribute is set and the corresponding target on the server side returns a correct JSON output (both JSON string and application/json header).

I call a fetch like this:

var athlete = new Athlete({ id: 1 });
athlete.fetch();

at this point if I add a

console.log(athlete);

I can see the model, and inspecting it in firebug I can open the attributes object and see all the values returned from the server.

BUT if I do a:

console.log(athlete.get('name'));

I get undefined (the name appears under the attributes in the DOM inspection I mentioned above)

also doing a:

console.log(athlete.attributes);

returns an object containing only {id: 1} which is the argument I passed while creating the model.

If I create the model like this:

var athlete = new Athlete(<JSON string copypasted from the server response>);

then everything works fine, the .get() method returns whatever I ask, and athlete.attributes shows all the values.

What am I doing wrong?

like image 644
Matteo Riva Avatar asked Mar 06 '12 13:03

Matteo Riva


2 Answers

fetch is asynchronous, which means that the data won't be available if you immediatly call console.log(athlete.get('name')) after the fetch.

Use events to be notified when the data is available, for example

var athlete = new Athlete({id: 1});
athlete.on("change", function (model) {
     console.log(model.get('name'));
});
athlete.fetch();

or add a callback to your fetch

var athlete = new Athlete({ id: 1 });
athlete.fetch({
    success: function (model) {
        console.log(model.get('name'));
    }
});

or take advantage of the promise returned by fetch:

athlete.fetch().then(function () {
    console.log(athlete.get('name'));
});
like image 130
nikoshr Avatar answered Nov 20 '22 10:11

nikoshr


Just as a quick remark when using events in this example. It did not work with change in my case because this events fire on every change. So sync does the trick.

var athlete = new Athlete({id: 1});
athlete.on("sync", function (model) {
   console.log(model.get('name'));
});
athlete.fetch();
like image 29
riasc Avatar answered Nov 20 '22 11:11

riasc