开发者

Backbone.js collection fetching with JSON

I'm using Backbone.js and Phil Sturgeon's CI rest server (AMAZING TOOL, definitely recommended).

Here is my page: http://interr0bang.net/7357/fetch/. It is very basic, a model (Event), a collection (Events), and a view (EventView). The collection is located at http://api.interr0bang.net/calendar/events and returns a JSON array that has been validated using jsonformatter.curiousconcept.com.

Here's the code:

$(function(){
    var Event = Backbone.Model.extend();
    var Events = Backbone.Collection.extend({
        model: Event,
        url: 'http://api.interr0bang.net/calendar/events',

    });
    var EventView = Backbone.View.extend({
        initialize: function(){
            _.bindAll(this, "render"开发者_如何学Go,"count");
            this.collection = new Events();
            this.collection.bind("change",this.count);
            this.collection.fetch();
            this.counter = this.collection.length;
            this.render();
        },
        render: function(){
            this.el.html(this.counter);
        },
        count: function(){
            this.counter = this.collection.length;
        }
    });
    eventView = new EventView({el:$('#collection')});
});

The view renders fine, but it always displays 0, and Firebug shows the GET request, and the status is 200 OK, but the response body is empty... Why doesn't this work?


You have a configuration problem. If you look at your browser, it reports:

XMLHttpRequest cannot load http://api.interr0bang.net/calendar/events. Origin     
http://interr0bang.net is not allowed by Access-Control-Allow-Origin.


I'm currently getting errors from both of the URLs you've posted.

http://interr0bang.net/7357/fetch/ = 404
http://api.interr0bang.net/calendar/events = Unreachable

On a side note, I find it best to keep things as separated as possible (models shouldn't know about views, views shouldn't know about models, etc). For that reason, I would recommend you don't instantiate the collection inside of the view.

Here is a refactored implementation of the above code:

$(function(){
  var
    Event = Backbone.Model.extend({})
    ,Events = Backbone.Collection.extend({
      model: Event
      ,url: 'http://api.interr0bang.net/calendar/events'
    })
    ,EventView = Backbone.View.extend({
      initialize: function(){
        _.bindAll(this, 'count');
        this.collection.bind('all', this.count);
      }
      ,count: function() {
        this.el.html(this.counter = this.collection.length);
      }
    })
    ,events = new Events()
    ,eventView = new EventView({
      el: $('#collection')
      ,collection: events
    })
  ;

  events.fetch();
});

Notice how I'm passing the collection to the view instead of it creating it itself. Also note that I removed the render method and combined it with count. Whenever the collection is changed (add, remove, reset), count will be called and the view will be updated.


You can not make cross domain Ajax calls, even between sub domains... So basically, your browser, on the domain interr0bang.net, blocks the Ajax call to your API on the domain api.interr0bang.net... This is the meaning the JavaScript warning:

Origin http://interr0bang.net is not allowed by Access-Control-Allow-Origin.

You could fix this by moving your API to the same domain, for instance: http://interr0bang.net/api/calendar/events if you can.

If you can not do that, you can authorize Ajax cross-domain calls by including some header in the response of your API methods. This is the CORS protocol, and it works with most modern browsers.

Here is another Stack Overflow answer concerning CORS that explains how it works: JSONP and Backbone.js


You should use the JSONP hack for get JSON data via cross-domain.

You can override the Backbone.js sync for work: Using JSONP with Backbone.js

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜