7

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","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?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • It is worth nothing that in this example, an attempt is made to bind to "change" to update the "count" of items. Perhaps this was valid in Sept. '11, but today you would bind to "add" or "remove" – cgp May 30 '13 at 18:27

4 Answers4

6

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.
Elf Sternberg
  • 16,129
  • 6
  • 60
  • 68
4

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.

fearphage
  • 16,808
  • 1
  • 27
  • 33
  • 2
    example would be better for beginners if you didn't use commas everywhere. – Ringo Aug 12 '12 at 06:41
  • I write code the way I would normally write code. I don't try to code for the lowest common denominator. If something is confusing to you, please feel free to request clarification. and how about this? https://gist.github.com/3d64cba0a37783ad745a – fearphage Aug 14 '12 at 19:48
4

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

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Tricote
  • 1,508
  • 1
  • 13
  • 21
0

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

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
bonaccorso.p
  • 160
  • 2
  • 6