Question

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?

Was it helpful?

Solution

(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.

OTHER TIPS

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()

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!'

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()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top