53

I have the following events for a Backbone View. Its a product view - with three tabs ("All", "Top 3", "Top 5")

Can I somehow pass a parameter into the method declaration so that it is equivalent to the following (this doesn't work)?

events : {
    "click #top-all":          "topProducts(1)"
    "click #top-three":      "topProducts(2)"
    "click #top-ten":         "topProducts(3)"
},
topProducts(obj){
    // Do stuff based on obj value
}
George Kagan
  • 5,913
  • 8
  • 46
  • 50
paddle42380
  • 6,921
  • 7
  • 32
  • 40

4 Answers4

83

You could put the extra argument in a data attribute on the clickable item instead; something like this:

<a id="top-all" data-pancakes="1">

And then topProducts can figure it out itself:

topProducts: function(ev) {
    var pancakes = $(ev.currentTarget).data('pancakes');
    // And continue on as though we were called as topProducts(pancakes)
    // ...
}
mu is too short
  • 426,620
  • 70
  • 833
  • 800
  • 2
    "this" points to the Backbone View here so doing a direct $(this) will not give the DOM element corresponding to the element clicked. – paddle42380 Oct 20 '11 at 07:16
  • 1
    @papdel: Right, sorry about that. But you can use `ev.target` (where `ev` is the event) instead. Have a look at my fixed version please. – mu is too short Oct 20 '11 at 18:16
  • Thanks, in general $(ev.target) gets you the dom element which triggered the event so this is immensely helpful. – paddle42380 Nov 06 '11 at 16:15
  • 2
    @papdel: Yeah, `ev.target` (when you can't rely on `this`) combined with data attributes is a great way to keep track of things. – mu is too short Nov 06 '11 at 18:48
  • 1
    @whistler: `{ 'click #top-all': 'topProducts', 'click #top-three': 'topProducts', ... }`. – mu is too short Apr 27 '12 at 21:59
  • Isn't there exist a way which is found in jquery to handle events ? `.eventName( [eventData ], handler(eventObject) )` – bitsbuffer Mar 11 '13 at 06:47
  • @Shubhmay: I'm not sure what you mean. Do you mean `x.click(...)` and such? You usually let Backbone handle events through delegation. – mu is too short Mar 11 '13 at 08:31
  • Is there any better solution out there to this? It seems crazy to me that you can't easily pass parameters to these events functions. Is there some good reason I'm not seeing? – streetlight Apr 05 '13 at 17:33
  • @streetlight: You could put functions (rather than names) in `events` but that's just shuffling things around. – mu is too short Apr 05 '13 at 17:57
  • 1
    @streetlight, try the below answer: arguments[0].currentTarget.id and you do not need to manipulate the DOM with an unnecessary data attribute. – Jordan May 17 '13 at 18:42
  • 2
    Can I just say, this is stupidly complex for something that should be extremely simple. Minus 5 points from the makers of backbone.js. – Ross Barbish Jun 05 '13 at 13:18
40

I generally prefer to do something like this:

events : {
   "click #top-all":    function(){this.topProducts(1);}
   "click #top-three":  function(){this.topProducts(2);}
   "click #top-ten":    function(){this.topProducts(3);}
},
topProducts(obj){
   // Do stuff based on obj value
}
Dre
  • 1,985
  • 16
  • 13
9

What you can do, is just check the id of the element which is received as currentTarget in arguments.

topProduct: function (e) {
    var id = e.currentTarget.id;
    if (id == "top-all") // Do something
    else if (id == "top-5") // Do something
    else if (id == "top-3") // Do something
}
Sachin Jain
  • 21,353
  • 33
  • 103
  • 168
  • 2
    This is actually better than the selected answer as it doesn't require any modification to the DOM. – ggutenberg Mar 09 '13 at 00:45
  • 2
    This answer is by far better than adding an unnecessary data attribute. – Jordan May 17 '13 at 18:41
  • If you want to get the class use `e.currentTarget.className` instead of `e.currentTarget.id`. Also, there are a lot interesting properties inside `e` object! – David Corral Aug 31 '17 at 11:18
  • @DavidCorral If you look at the sample given by OP, there is an Id mentioned on all the elements on which click handlers are attached. I agree with you on interesting properties on event object. – Sachin Jain Sep 01 '17 at 10:25
3

You can do so using closures:

EventObject.on(event, (function(){
    var arg = data; // Closure preserves this data
    return function(){
        doThis(arg);
    }   
})());