7

The Backbone 0.9.0 changelog says:

A view's events hash may now also contain direct function values as well as the string names of existing view methods.

When I try the following it fails, saying that the value for the event is undefined.

var BB = Backbone.View.extend({
  'initialize': function() {

    this.$el.html('<input type="button" value="Click me!" />');
    jQuery('body').html(this.el);
  },

  'events': {
    'click input[type="button"]': this.buttonClicked
  },

  'buttonClicked': function() {
    alert('button clicked!');
  }

});

window.b = new BB()

Am I misunderstanding the new feature? Can somebody explain how it works differently than I expected? Perhaps it's just my JavaScript syntax/value of 'this' at definition time that is borked.

The way I'm used to doing it still works:

'events': {
  'click input[type="button"]': 'buttonClicked'
},
mu is too short
  • 426,620
  • 70
  • 833
  • 800
aw crud
  • 8,791
  • 19
  • 71
  • 115

1 Answers1

14

When the JavaScript parser gets here:

'events': {
  'click input[type="button"]': this.buttonClicked
},

this is probably window, not an instance of BB as you expect. The window object doesn't have a buttonClicked property (at least it doesn't in your case) so you're really saying this:

'events': {
  'click input[type="button"]': undefined
},

and there's your error.

If you look at the source for delegateEvents, you'll see what the ChangeLog means:

delegateEvents: function(events) {
  // ...
  for (var key in events) {
    var method = events[key];
    if (!_.isFunction(method)) method = this[events[key]];
    // ...
  }
},

That _.isFunction call is what you're interested in. That means that you can say things like this:

events: {
  'click input[type="button"]': function() { alert('pancakes!') },
  'click button': some_function_that_is_in_scope
}

So you can put defined functions (either by their name if they're accessible or as function literals) in the events lookup table.

mu is too short
  • 426,620
  • 70
  • 833
  • 800
  • 1
    Very good, thank you. The only thing I wonder at this point is whether each anonymous function I defined (such as the 'pancakes!' one in your example) will have its value of 'this' scoped to the view, or if it will be whatever the target of the event is. It seems to me that this line would ensure it is scoped to the View itself: method = _.bind(method, this); – aw crud Feb 02 '12 at 19:42
  • 2
    @awcrud: Line 1078 (and this example: http://jsfiddle.net/ambiguous/JEavM/1/) indicate that the anonymous function will be scoped to the view. – mu is too short Feb 02 '12 at 20:15