Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Load data into a Backbone collection from JSON file?

I'm trying to load some data into a Backbone Collection from a local JSON file, using this very basic code:

  window.Student = Backbone.Model.extend({
  });
  window.Students = Backbone.Collection.extend({
    model: Student, 
  });
  window.AllStudents = new Students();
  AllStudents.fetch({ url: "/init.json"});
  console.log('AllStudents', AllStudents);

In the console statement, AllStudents is empty. But init.json is definitely being loaded. It looks like this:

[
  { text: "Amy", grade: 5 },
  { text: "Angeline", grade: 26 },
  { text: "Anna", grade: 55 }    
]

What am I doing wrong?

UPDATE: I've also tried adding a reset listener above the .fetch() call, but that's not firing either:

AllStudents.bind("reset", function() {
  alert('hello world');
});
AllStudents.fetch({ url: "/init.json"});

No alert appears.

UPDATE 2: Trying this script (reproduced here in full):

$(function(){
  window.Student = Backbone.Model.extend({
  });
  window.Students = Backbone.Collection.extend({
    model: Student, 
  });
  window.AllStudents = new Students();
  AllStudents.url = "/init.json";
  AllStudents.bind('reset', function() { 
      console.log('hello world');  
  }); 
  AllStudents.fetch();
  AllStudents.fetch({ url: "/init.json", success: function() {
      console.log(AllStudents);
  }});
  AllStudents.fetch({ url: "/init.json" }).complete(function() {
      console.log(AllStudents);
  });
});

Only one console statement even appears, in the third fetch() call, and it's an empty object.

I'm now absolutely baffled. What am I doing wrong?

The JSON file is being served as application/json, so it's nothing to do with that.

like image 651
Richard Avatar asked Feb 24 '12 13:02

Richard


3 Answers

The attribute names and non-numeric attribute values in your JSON file must be double quoted (" ") . Single quotes or no-quotes produces errors and response object is not created that could be used to create the models and populate the collection.

So. If you change the json file content to :

[
  { "text": "Amy", grade: 5 },
  { "text": "Angeline", grade: 26 },
  { "text": "Anna", grade: 55 }    
]

you should see the non-empty collection object.

You can change your code to see both success and failure as below:

    AllStudents.fetch({ 
    url: "/init.json", 
    success: function() {
          console.log("JSON file load was successful", AllStudents);
      },
    error: function(){
       console.log('There was some error in loading and processing the JSON file');
    }
  });

For more details, probably it will be a good idea to look in to the way ajax response objects are created.

like image 84
Praym Avatar answered Nov 11 '22 02:11

Praym


I/O operations in javascript are almost always asynchronous, and so it is with Backbone as well. That means that just because AllStudents.fetch has returned, it hasn't fetched the data yet. So when you hit your console.log statement, the resources has not yet been fetched. You should pass a callback to fetch:

AllStudents.fetch({ url: "/init.json", success: function() {
    console.log(AllStudents);
}});

Or optionally, use the new promise feature in jQuery (fetch will return a promise):

AllStudents.fetch({ url: "/init.json" }).complete(function() {
    console.log(AllStudents);
});
like image 10
Linus Thiel Avatar answered Nov 11 '22 04:11

Linus Thiel


fetch() returns a 'success' notification as already stated, but that just means that the server request was successful. fetch() brought back some JSON, but it still needs to stuff it into the collection.

The collection fires a 'reset' event when it's contents have been updated. That is when the collection is ready to use...

AllStudents.bind('reset', function () { alert('AllStudents bind event fired.'); });

It looks like you had this in your first update. The only thing I did differently was to put fetch() in front of the event binding.

like image 1
Mr The Falcon Avatar answered Nov 11 '22 04:11

Mr The Falcon