Adam Morris
Adam Morris

Reputation: 8545

Managing jQuery click events with backbone views

What's the best way of creating jQuery click events for a backbone view that is rendered multiple times? It seems like I should be using $().on() in my view's initializer, but this doesn't work unless I call it after it is rendered.

Basically, I'm rendering a table, and checking for click events on the rows. Here's what I'm trying (in coffeescript). This does not work -

class MyGridView extends Backbone.View
  el: '#myGrid'
  template: _.template(TableTmpl)

  initialize: -> 
    # $('tr',@el).on 'click', -> console.log($(@).attr('model')) # WRONG
    $(@el).on 'click', 'tr', -> console.log($(@).attr('model')) # CORRECT

  render: ->
    $(@el).empty()
    $(@el).append(@template({data: @collection.getPage()}))

This works, but does this create orphaned click events?

class MyGridView extends Backbone.View
  el: '#myGrid'
  template: _.template(TableTmpl)

  render: ->
    $(@el).empty()
    $(@el).append(@template({data: @collection.getPage()}))
    $('tr',@el).click -> console.log($(@).attr('model'))

UPDATE:

I was missing a parameter to $().on(), which is why it didn't work. I also tried events, which seems like a better way of handling this, which worked like:

class MyGridView extends Backbone.View
  el: '#myGrid'
  template: _.template(TableTmpl)
  events: {'click tr', 'selectModel'}

  selectModel: ->
    model = $(e.target).parent().attr('model')
    console.log(model)

  render: ->
    $(@el).empty()
    $(@el).append(@template({data: @collection.getPage()}))
    $('tr',@el).click -> console.log($(@).attr('model'))

Upvotes: 1

Views: 1129

Answers (2)

mu is too short
mu is too short

Reputation: 434685

You should be using the events property for this, that's what it is for:

class MyGridView extends Backbone.View
  el: '#myGrid'
  events:
    'click tr': 'click'
  template: _.template(TableTmpl)
  render: ->
    @$el.empty()
    @$el.append(@template({data: @collection.getPage()}))
    @
  click: ->
    console.log($(@).attr('model'))

Also note the switch to @$el since Backbone already has the jQuery wrapped el cached and that render usually returns the view. Furthermore, Backbone views have a $ method that is a shortcut for @$el.find(...) so you can say @$('tr') instead of $('tr', @el).

Demo: http://jsfiddle.net/ambiguous/ud6dU/

There's no need to mess around with manually binding events (in most cases). Views take care of all that for you using the view's events and a jQuery delegate attached to the view's el.

Upvotes: 1

spirit walker
spirit walker

Reputation: 304

I think you should either use live instead of on or you should use backbone's events object.

Upvotes: 1

Related Questions