How can I stop event propagation with Backbone.js?
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()
.
Gunnar Lium
Updated on August 08, 2020Comments
-
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 about 13 yearsNope. That will only stop the link from being opened.
-
Julien about 13 yearsIt 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 about 13 yearsIt seems like this is not working, probably due to how events are bound: api.jquery.com/event.stopPropagation
-
jbnunn over 12 yearsWow, worked for me too... are we writing bad functions that require us to do this, or is this normal behavior?
-
Tim Banks over 12 yearsYou 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 almost 11 yearsIt "works", but only in the sense that you get an
TypeError
(object has no method 'preventPropagation') which immediately stops the event from bubbling -
colllin over 10 years@YiJiang Did you try
stopDefault()
? ;) -
colllin over 10 yearsIn 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 theevent.target
against to the specified selector. -
sockmonk over 9 yearsBut 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.