sefner
sefner

Reputation: 103

Why are my CoffeeScript/backbone.js events not firing?

I'm trying to familiarize myself with CoffeeScript and backbone.js, and I must be missing something.

This CoffeeScript:

MyView  = Backbone.View.extend 
   events: { 
     "click" : "testHandler" 
   } 

   testHandler: -> 
     console.log "click handled" 
     return false 

 view = new MyView {el: $('#test_container')} 
 view.render()

Generates the following JavaScript:

(function() {
  var MyView, view;
  MyView = Backbone.View.extend({
    events: {
      "click": "testHandler"
    },
    testHandler: function() {
      console.log("click handled");
      return false;
    }
  });
  view = new MyView({
    el: $('#test_container')
  });
  view.render;
}).call(this);

But the click event does not fire testHandler when I click in test_container.

If I change the output JavaScript to:

$(function() {
  var MyView, view;
  MyView = Backbone.View.extend({
    events: {
      "click": "testHandler"
    },
    testHandler: function() {
      console.log("click handled");
      return false;
    }
  });
  view = new MyView({
    el: $('#test_container')
  });
  view.render;
});

Removing the call(this) and appending the $, everything works as expected. What am I missing?

Upvotes: 10

Views: 4514

Answers (4)

alecnmk
alecnmk

Reputation: 31

Try using CoffeeScript class declaration syntax, e.g.:

class BacklogView extends Backbone.View
  constructor: (@el) ->
    this.delegateEvents this.events

  events:
    "click" : "addStory"

  # callbacks
  addStory: ->
    console.log 'it works!'

Upvotes: 3

Dan Tocchini
Dan Tocchini

Reputation: 76

What happens when the view, or at least view.el is dynamically generated? You can call the view.delegateEvents() method to manually set the eventhandlers.

Here's similar coffeescript for rendering a ChildView in a ParentView then delegating the childView's events.

window.ParentView = Backbone.View.extend
  addOne: (thing) ->
    view = new ChildView({model: thing})
    this.el.append view.render().el 
    view.delegateEvents()

Upvotes: 2

Angiosperm
Angiosperm

Reputation: 454

(function () {}).call(this);

is just a way to immediately invoke an anonymous function while specifying a receiver. It works basically this same way as:

this.method = function () {};
this.method();

$(function () {}), at least in jQuery, is shorthand for

$(document).ready(function () {})

which runs the given function when the DOM tree has been fully constructed. It seems like this is the necessary condition for your Backbone.View.extend function to work properly.

Upvotes: 7

yfeldblum
yfeldblum

Reputation: 65435

For using CoffeeScript and jQuery together for application scripts, put your code in this sort of template:

$ = jQuery
$ ->

  MyView = Backbone.View.extend
    events:
      "click": "testHandler"
    testHandler: ->
      console.log "click handled"
      false

  view = new MyView el: $('#test_container')
  view.render()

Upvotes: 5

Related Questions