Praveen
Praveen

Reputation: 56501

Call functions within event handler

I have written two functions in JavaScript code as follows

Manager = FormManager.extend({
    First: function () {
     var response = this.Second("Feature"); //I'm able to get the alert
     
     //I have added a click event handler
     $('#element').on('click', function(){
       var newResponse = this.Second("Bug"); //The alert is not poping
     });

    }

    Second: function (type) {
     alert(type);
     //Performs certain operation
    }
});

Error: Uncaught TypeError: Object #<HTMLButtonElement> has no method 'Second'

I also tried without using this keyword like:

Second("Bug") // Error: There is no method

Whereas this a simplified format (in-order to show a simple example) on my program that I'm playing with. I'm struggling to find out the reason.

Can someone direct me to the right path?

Upvotes: 2

Views: 5412

Answers (2)

Alnitak
Alnitak

Reputation: 339786

Every time you use the this context variable in a function you have to consider what its value is.

Specifically that value will be whatever value the caller specified, whether by using myObj.mymethod(...), or mymethod.call(myObj, ...), or mymethod.apply(myObj, [ ... ]).

When your anonymous function $('#element').on('click', ...) is invoked jQuery will set the context to the HTML DOM element - it's no longer referring to your object.

The simplest work around is to obtain a copy of this outside of the callback, and then refer to that copy inside the closure, i.e.:

var that = this;
$('#element').on('click', function() {
     // use that instead of this, here
     console.log(this);    // #element
     console.log(that);    // your object
});

Another method is using Function.prototype.bind:

$('#element').on('click', (function() {
     console.log(this);    // your object
}).bind(this));

or with jQuery you can use $.proxy for the same effect, since .bind is an ES5 function.

I actually prefer the var that = this method, since it doesn't break the jQuery convention that this refers to the element associated with the event.

Upvotes: 2

PSL
PSL

Reputation: 123739

You are using incorrect this. try this way. this inside the handler represents #element not the context of the function itself.

 var self = this; //cache the context here
 $('#element').on('click', function(){
   var newResponse = self.Second("Bug"); //Access it with self
 });

Also i think you are missing a comma after First function definision and before Second function.

Fiddle

The reason being the callback you give gets invoked from within the context of the element so your this context changes. this context refers to the context from where the callback was invoked. But there are other ways to get around this like using $.proxy while binding your callback with jquery, using EcmaScript5 Function.prototype.bind etc. But ideally you don't want to do that because most of the cases you would need the context of the element there inside the handler.

Upvotes: 6

Related Questions