Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

backbone populate collection from external json

Below is the current code structure I have in place for a collection that I have manually constructed. I have a json file on my server which I am now trying to load in and basically remove the manual one and construct a collection based on that data. Was wondering what would I possibly need to change below to my code to help accommodate this.

        var Game = Backbone.Model.extend({
            defaults: {
                name: 'John Doe',
                age: 30,
                occupation: 'worker'
            }
        });


        var GameCollection = Backbone.Collection.extend({
            model: Game,
            url: 'path/to/json',

            parse: function(response) {
                return response;
            }
        });

        var GamesView = Backbone.View.extend({
            tagName: 'ul',

            render: function() {
                //filter through all items in a collection
                this.collection.each(function(game){
                    var gameView = new GameView({model: game});
                    this.$el.append(gameView.render().el);
                }, this)

                return this;
            }
        });

        var GameView = Backbone.View.extend({
            tagName: 'li',

            template: _.template($('#gameTemplate').html()),

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

        var gameCollection = new GameCollection([
            {
                name: 'John Doe',
                age: 30,
                occupation: 'worker'
            }, 
            {
                name: 'John Doe',
                age: 30,
                occupation: 'worker'
            }, 
            {
                name: 'John Doe',
                age: 30,
                occupation: 'worker'
            }
        ]);

        var gamesView = new GamesView({collection: gameCollection});

        $(document.body).append(gamesView.render().el);
like image 346
Anks Avatar asked Dec 15 '13 04:12

Anks


2 Answers

This is one of the many things to love about Backbone. I don't know what you are using for your backend, but you state that you have a json file on your server, hopefully a json file full of the models that should be in your collection. And now here is the magic code (drumroll please..):

var GameCollection = Backbone.Collection.extend({
  model: Game,
  url: 'path/to/json/on/external/server',
});

var gameCollection = new GameCollection();
gameCollection.fetch();

Not much to it, right? Of course there are several options you can add or change to a fetch, so check out the docs here: http://backbonejs.org/#Collection-fetch. Backbone uses jQuery.ajax() be default, so check out the docs here to see all of the options: http://api.jquery.com/jQuery.ajax/

You shouldn't need the custom parse in your collection unless your models on the server don't match your backbone models.

Things to know: fetch is asynchronous. It takes time to talk to the server, and the rest of your javascript will move on and complete. You will probably need to at least add a callback function to the success option, which will be called when fetch is finished, and it is good to add something to error as well, in case something goes wrong. You can add data as a query string so that your backend can use it using the data option, the data has to be an object. Here is an example:

gameCollection.fetch({
  data: {collection_id: 25},
  success: function(){
    renderCollection(); // some callback to do stuff with the collection you made
  },
  error: function(){
    alert("Oh noes! Something went wrong!")
  }
});

fetch should receive data as JSON, so your url should either exclusive return JSON or be set up to detect an AJAX request and respond to it with JSON.

like image 116
RustyToms Avatar answered Nov 20 '22 17:11

RustyToms


Firstly you need to fetch it from server as RustyToms said. And the other consideration is how to force the collection view to render itself again once data collected from server, as muistooshort commented.

If you manipulating fetch or sync you'll need to do it multiple times when there are more than one collection in app.

Doing such is native with Marionette, but in plain Backbone you can mimic the method of Marionette's CollectionView and do such:

//For the collection view
var GamesView = Backbone.View.extend({
  initialize: function({
    this.listenTo(this.collection, 'reset', this.render, this);
  });
  // Others
});

Then, when collection data fetched from server, the collection will trigger a reset event, the collection view noticed this event and render itself again.

For more than one collections, you can extract the code into a parent object in app and inherit from that.

var App.CollectionView = Backbone.View.extent({
  initialize: //code as above
});

var GamesView = App.CollectionView.extend({
  //Your code without initialize
});
like image 41
Billy Chan Avatar answered Nov 20 '22 17:11

Billy Chan