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

2

5

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?

Alexi answered 13/6, 2012 at 21:30 Comment(0)
R
11

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.

Robenarobenia answered 13/6, 2012 at 22:1 Comment(10)
+1, Yes, same opinion here. I'm also having problems to have a working example, the onlive created DOM element is not triggering change event, I gave up due it was not a problem related to the question.Zenia
@fguillen: I half-undid the edit, I think .on is doing an isPlainObject check on its first argument to choose which form it is using, the first argument isn't an event-map so it goes with the first form of .on and we're back trying to call a view object like a function. Are you having the "change isn't triggered until focus changes" problem?Robenarobenia
@muistooshort, this is perfect. Thank you for the explanation and the code sample. This way is much better and it works great. I had to change the events selection to change #color to get it working, but other than that it is great. Thanks again.Alexi
@fguillen: I had the event spec backwards, 'input change' should have been (and now is) 'change input': jsfiddle.net/ambiguous/xD7XmRobenarobenia
@Brandon: I had the event spec backwards (duh!), see my last comment to fguillen.Robenarobenia
@muistooshort you see, I knew I was missing something, just the number of arguments... to easy :PZenia
@muistooshort about the Are you having the "change isn't triggered until focus changes" problem? I didn't know about this issue but it is very probable. In my experiments I was modifying colorInput.val() by code and the event was no triggered, like here: jsfiddle.net/fguillen/qZ8aNZenia
@fguillen: The event isn't triggered until the value changes and there is a focus change (more or less): https://mcmap.net/q/429660/-onchange-event-not-fire-when-the-change-come-from-another-functionRobenarobenia
@muistooshort this HTML specifications were done before JS was implemented :)... I see, if we go with the book the behavior is the proper one, still I have opened a jQuery bug just to make noise about this.Zenia
Although your comment didn't directly apply, you did help me out by giving me a clue as to what was happening, so +1 to you. I was trying to call lodash's debounce() in a window scroll handler, but I had a typo and was passing the debounce()'s params to on()'s.Byran
S
3

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.

Shirting answered 14/6, 2015 at 14:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.