Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trying to bind a callback by passing in the function throws an error

I just want to fire an event when an input changes value using jQuery 1.7.2 and Backbone.js.

Currently I have the following (which works)

MyView: Backbone.View.extend({
  initialize: function() {

    this.colorInput = $("<input />", {
         "id": "color",
         "name": "color",
         "value": this.model.get("color")
    });

    var self = this;
    this.colorInput.on("change", function() {
      self.changeColor();
    });

  },
  changeColor: function() {
    var color = this.colorInput.val();
    this.model.set("color", color);
  }
});

I was trying to do it the other way where I just pass in my function.

this.colorInput.on("change", this.changeColor, this);

But when trying to do it that way, it throws the error

((jQuery.event.special[handleObj.origType] || {}).handle || handleObj.handler).apply is not a function
.apply( matched.elem, args );

(line 3332)

Which I'm not able to figure out. Any ideas why this way doesn't work?

like image 657
Brandon Avatar asked Jun 13 '12 21:06

Brandon


People also ask

How do you bind a callback function?

Explicitly set this of the callback - part 1 bind [docs], which returns a new function with this bound to a value. The function has exactly the same behavior as the one you called . bind on, only that this was set by you. No matter how or when that function is called, this will always refer to the passed value.

What is execution context of callback function?

Pro tip: When a function (callback) is invoked, the JavaScript interpreter creates an execution record (execution context), and this context contains information about the function. Amongst other things is the this reference, which is available for the duration of the function's execution.


2 Answers

You're confusing jQuery's on:

.on( events [, selector] [, data], handler(eventObject) )
.on( events-map [, selector] [, data] )

with Backbone's on:

object.on(event, callback, [context])

Backbone's takes a context as the third argument, jQuery's doesn't. Looks like jQuery's on is interpreting your third argument as the handler(eventObject) and trying to call it like a function, that would explain the error message that you're seeing.

Normally you'd do it more like this:

MyView: Backbone.View.extend({
  events: {
    'change input': 'changeColor'
  },
  initialize: function() {
    this.colorInput = $("<input />", {
       "id": "color",
       "name": "color",
       "value": this.model.get("color")
    });
  },
  render: function() {
    this.$el.append(this.colorInput);
    return this;
  },
  changeColor: function() {
    var color = this.colorInput.val();
    this.model.set("color", color);
  }
});

and let Backbone's event delegation system take care of things.

like image 142
mu is too short Avatar answered Oct 05 '22 13:10

mu is too short


This is for the Googlers who come across this problem. I had this exact same issue and what occurred was that where the error was being reported and where the error actually occurred were in two different places.

One line of code was obsolete and looked something like

$('#modal').on('click', function(e) {
   // Execute invalid code here.
});

The other line of code was similar:

$('#modal').on('click', function(e) {
   // Execute valid code here.
});

The error was that the first invocation was not a true function, so the error was accurate, the second handler being invoked was not a true function and jQuery couldn't complete it, but it always acted as if it occurred on the second function call.

I'd say if you run into this error, remove any extra event handlers that may be triggered and see if that stops the problem.

like image 23
Michael Ryan Soileau Avatar answered Oct 05 '22 13:10

Michael Ryan Soileau