20

I am using Backbone and I have a view with events defined:

    ....
    events: {
        'click .search-button': 'setModelTerm',
        'change .source-select': 'setModelSourceId',
        'change .source-select': 'activateSource'
    },
    ....

I would like to trigger two methods when the event change .source-select fires. The problem is that the last entry in the event object overrides the preceding entry.
How can I trigger two methods in one event?
(I am trying to prevent writing another method that calls those two methods)

Jack
  • 10,943
  • 13
  • 50
  • 65
Naor
  • 23,465
  • 48
  • 152
  • 268

3 Answers3

42

You can pass a wrapper function in your hash of events to call your two methods.

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

Events are written in the format {"event selector": "callback"}. The callback may be either the name of a method on the view, or a direct function body.

Try

events: {
    'click .search-button': 'setModelTerm',
    'change .source-select': function(e) {
        this.setModelSourceId(e);
        this.activateSource(e);
    }
},
nikoshr
  • 32,926
  • 33
  • 91
  • 105
  • 2
    I wrote it specifically! "I am trying to prevent writing another method that calls those two methods". – Naor Nov 13 '12 at 17:00
  • @Naor If you want to declare something like `'change .source-select': 'setModelSourceId activateSource'`, you'll have to override view.delegateEvents http://documentcloud.github.com/backbone/docs/backbone.html#section-156 which seems slightly overkill to me – nikoshr Nov 13 '12 at 17:11
  • Is there any way to to give a single function for multiple events? – Prasanna Nov 19 '13 at 12:20
  • 1
    @Prasanna You can pass the same target function multiple times, something like `events: {'event1': 'name_of_function', 'event2': 'name_of_function'}` assuming `name_of_function` is defined on the prototype of your view – nikoshr Nov 19 '13 at 12:48
  • 1
    thanks but i solved it this way events : {'click #btn1,#btn2,': 'function'} – Prasanna Nov 19 '13 at 13:04
  • 1
    I don't get why backbone allows multiple events one function and not multiple functions one event... – Vic Jan 24 '14 at 15:10
7

The only thing that is keeping you from adding the same event/selector pair is that events is a hash - jQuery can handle multiple bindings to the same element/event pair. Good news though, jQuery events allow you to namespace events by adding a .myNamespace suffix. Practically speaking, this produces the same results but you can generate many different keys.

var MyView = Backbone.View.extend({
  events: {
    'click.a .foo': 'doSomething',
    'click.b .foo': 'doSomethingElse'
    'click.c .foo': 'doAnotherThing', // you can choose any namespace as they are pretty much transparent.
  },

  doSomething: function() {
    // ...
  },

  doSomethingElse: function() {
    // ...
  },

  doAnotherThing: function() {
    // ...
  },
});
Kent Willis
  • 380
  • 3
  • 11
1

The events hash in your view is just a convenience "DSL" of sorts. Just bind your 2nd event manually inside initialize.

events: {
    'click .search-button': 'setModelTerm'
},
initialize: function () {
    _.bindAll(this);
    this.on('click .search-button', this.doAnotherThing);
}
Peter Lyons
  • 142,938
  • 30
  • 279
  • 274
  • 1
    This is wrong. Using this.on binds to Backbone.Events mixin to the view not the DOM events. If you want to manually add DOM event callbacks, use: `this.$el.on('click', '.search-button', this.doAnotherThing);` which is what the `events` hash does behind the scenes. – Kent Willis Apr 18 '16 at 14:47
  • And if you want them to be undelegated with the rest of the events on `undelegateEvents`, add this suffix to the event name: `'click.delegateEvents' + this.cid` – Kent Willis Apr 18 '16 at 14:53
  • 1
    @KentWillis can you post an answer with the correct code please? – Peter Lyons Apr 18 '16 at 19:19
  • 1
    Found a better way to solve this and posted it as an answer. But if you still want to manually add an event, do: ```this.$el.on('click.delegateEvents' + this.cid, '.search-button', this.doAnotherThing);``` in an override of the ```delegateEvents```. Make sure to call ```Backbone.View.prototype.delegateEvents.call(this);``` at the beginning of the override. This will let the view manage this custom DOM event callback alongside the other events. – Kent Willis Apr 20 '16 at 17:06