1

I'm just starting to play around with Backbone. I've got a view associated with a collection, and I want to render the view when the collection successfully syncs with the server.

I've managed to get my collection to sync successfully -

  var MyCollection = Backbone.Collection.extend({
    model: Backbone.Model,
    url: '/api/cart/lineitem'
  });

  var myCollection = new MyCollection();

  myCollection.fetch({
    success: function() {
      console.log('fetched ' + myCollection.length + ' objects');
    }
  });

The console shows that the fetch function works.

However I'm getting some strange behaviour in my view. I can't seem to get the render function to run.

  var MyView = Backbone.View.extend({

    el: $('#mini_cart'),

    cartTpl: _.template($('#miniCartTemplate').html()),

    initialize: function() {
      this.listenTo(this.collection, 'reset', this.render);
      this.listenTo(this.collection, 'reset', console.log('collection reset'));
    },

    render: function(){
      console.log('rendering MyView');
    }

  });

  var myView = new MyView({
    collection: new MyCollection()
  });

The console shows that the event fires but it never enters into the render method (ie I get the 'collection reset' message but never the 'rendering MyView' message). I don't really understand what's going on (I don't really see how the reset event is being fired on my collection at all).

4

4 回答 4

1
this.listenTo(this.collection, 'reset', console.log('collection reset'));

The third paramter of listenTo has to be a function, not a method call (which doesn't return a function). Try to remove this line or just wrap the console.log call into a function like this:

 this.listenTo(this.collection, 'reset', function(){console.log('collection reset');});
于 2013-08-28T12:39:51.597 回答
1

I don't know if this method is the most clean one, but I fetch in my router and redirect once the request was done:

index: ->
    self = @
    @subscribes.fetch {
        url: "/subscribes/getbyfacebookid/#{self._options.request.user_id}.json",
        success: (data, xhr) ->
            console.log data
            if data.length == 0 then self.dispIndex() else self.social()
        }

dispForm: ->
    self = @
    $("#app div").html ''
    $("#app center").fadeIn 'fast', () ->
        FB.api 'me', (data) ->
            self.view = new Formapp.Views.Subscribes.NewView(data: data, collection: self.subscribes)
            $("#app center").fadeOut 'fast', () ->
                $('#app div').html(self.view.render().el)

dispIndex: ->
    self = @
    @view = new Formapp.Views.Subscribes.IndexView(@_options)
    $("#app center").fadeOut 'fast', () ->
        $('#app div').html(self.view.render().el)
于 2013-08-28T12:40:12.467 回答
1

It looks like you're calling fetch on one instance of your collection and then passing another (new) instance to the view. This means the 'reset' event is never fired on the instance used by the view.

 var myView = new MyView({
    collection: myCollection // use the instance you're going to call fetch on
  });

Your console.log statement is executed as soon as the render method is called and not when the 'reset' event is fired. That's why you're seeing that log statement but not the one in the render method. What you probably want to do is this:

// Pass a function to the listenTo method which will be executed when the event fires
this.listenTo(this.collection, 'reset', function() {
    console.log('collection reset') 
});
于 2013-08-28T12:44:32.117 回答
0

Create a callback:

myCollection.on('reset', myView.render);

Also consider using a listener from the view

myView.listenTo(myCollection, 'reset', this.render)
于 2013-08-28T12:40:03.327 回答