How can I stop event propagation with Backbone.js?

27,440

Solution 1

I've been using e.stopImmediatePropagation(); in order to keep the event from propagating. I wish there was a shorter way to do this. I would like return false; but that is due to my familiarity with jQuery

Solution 2

The JQuery preventDefault method would also be a good option.

    window.LocationViewLI = Backbone.View.extend({
        tagName: "li",
        template: _.template('<a href="/locations/<%= id %>"><%= name %></a>'),

        events: {
            "click a": "handleClick"
        },      
        handleClick: function(event) {
            event.preventDefault();
            console.log("LocationViewLI handleClick", this.model.escape("name") );
            // debugger;
        },
        ...

Solution 3

Each of your event handlers will be passed an event object when it's triggered. Inside your handler, you need to leverage jQuery's event.stopPropagation() method. For example:

link: function(event) {  
  //do some stuff here
  event.stopPropagation();
}

Solution 4

Two other methods that might work for you:

1

events: {
    'click a': 'link', 
    'click *:not(a, a *)': 'openPanel' 
}

Then openPanel will not capture click events on any <a> or child of an <a> (in case you have an icon in your <a> tag).

2

At the top of the openPanel method, make sure the event target wasn't an <a>:

openPanel: function(event) {
    // Don't open the panel if the event target (the element that was
    // clicked) is an <a> or any element within an <a>
    if (event && event.target && $(event.target).is('a, a *')) return;

    // otherwise it's safe to open the panel as usual
}

Note that both of these methods still allow the openPanel function to be called from elsewhere (from a parent view or another function on this view, for example). Just don't pass an event argument and it'll be fine. You also don't have to do anything special in your link function -- just handle the click event and move on. Although you'll probably still want to call event.preventDefault().

Share:
27,440
Gunnar Lium
Author by

Gunnar Lium

Updated on August 08, 2020

Comments

  • Gunnar Lium
    Gunnar Lium over 3 years

    Using a Backbone.js View, say I want to include the following events:

        events: {
            'click a': 'link', 
            'click': 'openPanel' 
        }
    

    How can I avoid openPanel to be fired when I click on a link. What I want is to have a clickable box which will trigger an action, but this box can have elements which should trigger other actions, and not the parent action. Think for example Twitter.com, and links in Tweets/right hand panel.

  • Gunnar Lium
    Gunnar Lium about 13 years
    Nope. That will only stop the link from being opened.
  • Julien
    Julien about 13 years
    It is a jQuery event, just stop propagation like you do in jQuery. The first arg of the "link" function is the jQuery event.
  • Gunnar Lium
    Gunnar Lium about 13 years
    It seems like this is not working, probably due to how events are bound: api.jquery.com/event.stopPropagation
  • jbnunn
    jbnunn over 12 years
    Wow, worked for me too... are we writing bad functions that require us to do this, or is this normal behavior?
  • Tim Banks
    Tim Banks over 12 years
    You aren't writing bad functions. That is one of the default ways to stop propagation in javascript. I haven't looked at backbone recently, but they may have introduced an alternative method.
  • Yi Jiang
    Yi Jiang almost 11 years
    It "works", but only in the sense that you get an TypeError (object has no method 'preventPropagation') which immediately stops the event from bubbling
  • colllin
    colllin over 10 years
    @YiJiang Did you try stopDefault()? ;)
  • colllin
    colllin over 10 years
    In Backbone views, there's no 'propagation' going on between the view events -- all of the events are delegated to the same DOM element (view.el) but then capture bubbled events and filter the event.target against to the specified selector.
  • sockmonk
    sockmonk over 9 years
    But this does NOT have the same behavior. preventDefault stops user from going to the link's href. stopImmediatePropagation allows the user to go to the link's href as intended, but stops the click event from propagating to the outer handler.