Backbone events not binding to dom element
Asked Answered
T

3

5

In one of my views I have:

events: {
    'click .tab': 'doSomething',
},

then:

doSomething: function(){
    ...
},

This is a recurring structure in my views, but for some reason the 'doSomething' function is not being triggered by the click in this view.

When are the elements being bound to the event?

Any tips on debugging this?

Tergiversate answered 15/9, 2012 at 0:13 Comment(0)
W
10

link to fiddle here : http://jsfiddle.net/7xRak/

Omitting the selector causes the event to be bound to the view's root element (this.el).

if your class="tab" is views DOM element means this.el then you should bind event as

events : {
  'click' : 'dosomething'
}

and for inner element in this.el like

<div class="tab">
     <span class="inner"></span>
</div>

then you should bind event as,

  events : {
      'click' : 'dosomething'
      'click .inner' : 'onInnerClick'
    }

document : http://backbonejs.org/#View-delegateEvents

Wainscot answered 15/9, 2012 at 4:49 Comment(1)
This is exactly what I'm showing above, I'm well aware of this pattern. What I'm trying to say is that this pattern for some reason is not working, so what are some ways to debug the event delegation.Tergiversate
J
7

The delegation happens during the delegateEvents method at the end of the view constructor.

http://documentcloud.github.com/backbone/docs/backbone.html#section-144

Try manually calling this.delegateEvents() inside render before returning this. Are you futzing with this.el inside your initialize or render methods in a way that backbone isn't expecting?

Jodyjoe answered 15/9, 2012 at 0:16 Comment(2)
Hm, I just tried calling the this.delegateEvents() before the return in the render but it's still not binding the events. Also, I'm not messing with the this.el inside either the initialize or the render. The only thing that worked was calling var that = this; this.$('.tab').on('click',function(){that.doSomething();}); inside of the initialize, but this feels like bad form...Tergiversate
I wasn't messing with $el or el either, but adding delegateEvents to my render fixed the event binding.Abductor
A
0

I think this might be related to event bubbling. In my case specifically, I have a <details> element and I was trying to bind to its toggle event, but backbone delegates events, (as the method name suggests), meaning that it will attach an event handler to the view's root element. As the event bubbles up the DOM tree up to the root element, backbone (or jquery) then checks if the event originates from an element that matches the selector you gave it.

But: the toggle event does not bubble: https://developer.mozilla.org/en-US/docs/Web/API/HTMLDetailsElement/toggle_event

This event is not cancelable and does not bubble.

So, maybe in the OP's case the code handling the tabs (bootstrap perhaps?) cancels the event bubbling before it reaches the view root element.

In my case this code does not work:

this.$el.on('toggle', 'details', (evt) => {console.log('toggle event on the root element', evt);});

while this code does work:

this.$el.find('details').on('toggle', (evt) => {console.log('toggle event on the details element itself', evt);});
Atul answered 3/9 at 9:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.