Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Backbone Event of Subview not firing correctly

I have a Gallery in Backbone consisting of GalleryItem subviews.

The problem I am having right now is that the events are not firing correctly on the subview.

Here is the code of my GalleryItemView:

// Gallery View: Displays a Single Image Element
var GalleryItemView = Backbone.View.extend({
  el: '#isotope',

  events: {
    "click .hoverbox": "onHoverBoxClick"
  },


  initialize: function () {
    this.template = Hogan.compile($("#gallery-item-template").html());
  },

  render: function () {
    this.$el.append(this.template.render(this.model.toJSON())); 
    return this;
  },
  onHoverBoxClick: function () {
    console.log("clicked: ", this.model.id);
  }

});

I expected that each element fires the onHoverBoxClick event when clicking on the .hoverbox div. But it does nothing. If I add this to the View:

el: "#mydiv"

then it fires the event, but for every GalleryItemView. (So for 8 subviews I get 8 console.logs also I clicked only one)

my template of subview looks like this:

<script type="text/x-handlebars-template" id="gallery-item-template">
  <div class="item {{tags}}" style="width: auto;">
    <img class="eveimage" src="{{image_medium_url}}">
    <div class="hoverbox down"><span>{{tags}}</span>    </div>
</div>
</script>

And the collection view of the gallery looks like this (this is where I instantiate the gallery items):

// Gallery View: Displays the main image / project gallery
window.views.GalleryView = Backbone.View.extend({
  el: '#isotope_container',
  className: 'no-transition',
  template: _.template($("#gallery-template").html()),

  initialize: function() {
    this.collection = new gallery();
    this.$el.append(this.template);
    this.collection.on('reset', this.render, this);
  },

  render: function(){  
    console.log("ich render nei");
    this.collection.forEach(this.addOne, this);  

  },  
  addOne: function(model){  
    var itemView = new GalleryItemView({model: model});
    var el = itemView.render().el;

    this.$el.append(el);  
  }
});

Any ideas why that is?? thanks...

like image 735
tmaximini Avatar asked Dec 03 '25 12:12

tmaximini


1 Answers

When you specify an events hash on a Backbone view, Backbone uses the jQuery .delegate method to bind callbacks, with the View's el as the root element. However, in your GalleryItemView.render method, you are not actually rendering to the view's el; you're selecting a completely different element. Because of this, the event is actually firing outside of what your events hash is scoped to.

Instead, you need to do something like this

window.views.GalleryItemView = Backbone.View.extend({
   ...
  render:function () {
    this.$el.append(this.template.render(this.model.toJSON())); 
    return this;
  }, 
  ...
});

Looking at your current code, the render method you have defined on GalleryView is just appending a bunch of empty <div> tags. The fact that you're selecting an existing element on the page and appending your interpolated template within the GalleryViewItem.render method is what is actually causing your items to appear at all.

[[PART 2]] With your edited view, you've provided an ID selector as the el property on GalleryItemView. Because of this, plus the way you're rendering each item view using .append(), you're still attaching every GalleryItemView instance to the same element. Since they are all sharing the same root element, when events are delegated, an event on one will cause the handlers for every GalleryItemView to be invoked.

What you should have is something like the following:

GalleryItemView = Backbone.View.extend({
  // remove the ID selector for the el property -- don't need it
  ...
  render:function() {
    this.$el.html(this.template.render(this.model.toJSON()));
    return this;
  }
  ...
});

window.views.GalleryView = Backbone.View.extend({
  ...
  addOne: function(model){  
    var itemView = new GalleryItemView({model: model});
    var el = itemView.render().el;

    // assuming you actually intended to attach all 
    // GalleryItemViews to the #isotope element
    this.$('#isotope').append(el);  
  }
  ...
});
like image 132
philm Avatar answered Dec 06 '25 02:12

philm



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!