0

I have the following code for one of my backbone views:

class GD.Views.Result extends Backbone.View
  template: JST['mobile/templates/result']
  tagName: 'tr'
  className: 'result'
  events:
    'click' : 'showDetail'
    'click #favourite' : 'addFavourite(Favourite)'
    'click #like' : 'addFavourite(Like)'
    'click #dislike' : 'addFavourite(Dislike)'
   render: ->
     $(@el).html(@template(model: @model))
     this
   addFavourite: (type) ->
     event.preventDefault()
     attributes =
       id: @model.id
       type: type
       cluster: @model.cluster
     @collection.create attributes,
     wait: true
     success: @updateIcons
     error: @handleError
   showDetail: ->
     ...
   updateIcons: ->
     ...
   handleError: ->
     ...

And I'm getting this error in my console:

Uncaught Error: Method "addFavourite(Favourite)" does not exist

I don't really understand why this happens for the AddFavourite method and not the showDetail one - are you not allowed to pass methods which require defined arguments to any event?

Many thanks in advance for any help(!)

socratic_singh
  • 183
  • 1
  • 13

2 Answers2

4

As @Derick explained, if the value of an events element is a string, it names a method on your view object, so you can't specify parameters that way. You need to either (examples are in JS):

  1. Supply just the method name as a string, and then determine the type in the method. E.g.

    events : {
    
      'click #favourite' : 'addFavourite',
    
      'click #like' : 'addFavourite',
    
      'click #dislike' : 'addFavourite'
    
    }
    

    addFavourite : function ( event ) {
    
      event.preventDefault();
    
      var type = event.target.id;
    
    }
    
  2. Suppy a function object (in this example, via a function expression). In this case you could supply a function that calls your generic addFavorite method and passes it the type, e.g.:

    events : {
    
      'click #favourite' : function ( event ) {
    
        this.addFavourite( event, 'favourite' );
    
      },
    
    
      'click #like' : function ( event ) {
    
        this.addFavourite( event, 'like' );
    
      },
    
    
      'click #dislike' : function ( event ) {
    
        this.addFavourite( event, 'dislike' );
    
      }
    
    }
    

    addFavourite : function ( event, type ) {
    
      event.preventDefault();
    
    }
    

From what I can see in your example, I'd go with option #1.

Note that this could could be made more dynamic, e.g.:

events : function () {

  var events = {};

  var view = this;

  [

    'favourite',

    'like',

    'dislike'

  ].forEach( function ( type ) {

    events[ "click #" + type ] = ( function ( type ) {

      return function ( event ) {

        view.addFavourite( event, type );

      };

    } )( type );

  };


  return events;

}    
JMM
  • 26,019
  • 3
  • 50
  • 55
1

Don't specify the parameters in the events configuration. The event config is used as a lookup, which is done by name, not by method signature.

class GD.Views.Result extends Backbone.View
  template: JST['mobile/templates/result']
  tagName: 'tr'
  className: 'result'
  events:
    'click' : 'showDetail'
    'click #favourite' : 'addFavourite'
    'click #like' : 'addFavourite'
    'click #dislike' : 'addFavourite'
   render: ->
     $(@el).html(@template(model: @model))
     this
   addFavourite: (type) ->
     event.preventDefault()
     attributes =
       id: @model.id
       type: type
       cluster: @model.cluster
     @collection.create attributes,
     wait: true
     success: @updateIcons
     error: @handleError
   showDetail: ->
     ...
   updateIcons: ->
     ...
   handleError: ->
     ...
Derick Bailey
  • 72,004
  • 22
  • 206
  • 219