12

Okay, so I've read several other questions regarding Backbone views and events not being fired, however I'm still not getting it sadly. I been messing with Backbone for about a day, so I'm sure I'm missing something basic. Here's a jsfiddle with what I'm working with: http://jsfiddle.net/siyegen/e7sNN/3/

(function($) {

    var GridView = Backbone.View.extend({
        tagName: 'div',
        className: 'grid-view',
        initialize: function() {
            _.bindAll(this, 'render', 'okay');
        },
        events: {
            'click .grid-view': 'okay'
        },
        okay: function() {
            alert('moo');
        },
        render: function() {
            $(this.el).text('Some Cow');
            return this;
        }
    });

    var AppView = Backbone.View.extend({
        el: $('body'),
        initialize: function() {
            _.bindAll(this, 'render', 'buildGrid');
            this.render();
        },
        events: {
            'click button#buildGrid': 'buildGrid'
        },
        render: function() {
            $(this.el).append($('<div>').addClass('gridApp'));
            $(this.el).append('<button id="buildGrid">Build</button>');
        },
        buildGrid: function() {
            var gridView = new GridView();
            this.$('.gridApp').html(gridView.render().el);
        }

    });

    var appView = new AppView();

})(jQuery);

The okay event on the GridView does not fire, I'm assuming because div.grid-view does not exist when the event is first bound. How should I handle the binding and firing of an event that's built on a view dynamically? (Also, it's a short example, but feel free to yell at me if I'm doing anything else that I shouldn't)

Thaddeus Albers
  • 4,094
  • 5
  • 32
  • 42
siyegen
  • 123
  • 1
  • 1
  • 5
  • because `el` is div tag with `.grid-view` . and you are finding `.grid-view` class name element in that div . which you won't get it . – Mahi Nov 21 '16 at 17:11

1 Answers1

23

Your problem is that the events on GridView:

events: {
    'click .grid-view': 'okay'
}

say:

when you click on a descendent that matches '.grid-view', call okay

The events are bound with this snippet from backbone.js:

if (selector === '') {
  this.$el.on(eventName, method);
} else {
  this.$el.on(eventName, selector, method);
}

So the .grid-view element has to be contained within your GridView's this.el and your this.el is <div class="grid-view">. If you change your events to this:

events: {
    'click': 'okay'
}

you'll hear your cows (or "hear them in your mind" after reading the alert depending on how crazy this problem has made you).

Fixed fiddle: http://jsfiddle.net/ambiguous/5dhDW/

mu is too short
  • 426,620
  • 70
  • 833
  • 800
  • That worked, thanks. In general, if I want to bind an event to the element the view itself is creating, I'd leave out the selector? I tested that and it works with another view, just making sure that's the right way to go about things. – siyegen Sep 25 '11 at 01:11
  • @siyegen: Right. Have a look at the first branch of the `backbone.js` snippet I included; if there is no selector, then the event is bound directly to `this.el` using `$(this.el).bind(eventName, method);`, if there is a selector then the event is bound with `delegate`. – mu is too short Sep 25 '11 at 01:18
  • but what when I want to fire event only when `this.el` has `grid-view` class ? – Jashwant Jan 28 '13 at 14:08
  • @Jashwant: You'd probably have to check `this.$el.hasClass('grid-view')` inside the click handler or manually add and remove a raw click handler as needed without going through `events`. – mu is too short Jan 28 '13 at 18:22
  • @muistooshort, Okay so there's no direct way. – Jashwant Feb 03 '13 at 09:11