Wednesday, March 14, 2012

Find the jQuery Bug #7: Using a Method as an Event Handler

Introduction


In this open-ended series I'll be showcasing a snippet of buggy jQuery code that you might encounter, explain what the problem is, and then identify how you can easily resolve the issue.

You can view other posts in this series...

The Desired Feature


We want to use an existing object's method to be invoked when the user clicks on a button.


The Buggy Code


The following code snippets is our first attempt at solving the problem, but there is a subtle error. Do you see it?


You can view, run, and edit the above code sample from the following embedded jsFiddle.



The result that we expected was to see was an alert box showing up when the user clicks the Register button, but instead the following error shows up in the console.


The Underlying Problem


At the root of the problem is that once the event handler is invoked jQuery makes sure the this pseudo parameter is set to the DOM element that caused the event.


Inside of the conference.register method listed above, the this parameter refers to the register button DOM element. Since this is a DOM element that is why we are getting the "Cannot call method 'push' of undefined" error.

What we need to resolve this issue is a way to control the value of the this parameter when the conference.register method is invoked. Thankfully, there is a way in jQuery to do this.

A Solution


The solution to fix this problem is really simple and straightforward. As of version 1.4, jQuery added the $.proxy() method to help solve the bug found in the previous example.

jQuery.proxy( function, context )
Returns: Function
Takes a function and returns a new one that will always have a particular context.

-- http://api.jquery.com/jQuery.proxy/

In order to fix our example we just need to wrap the conference.register method with the $.proxy() method and provide the context that we want the pseudo this parameter to represent.


You can view, run, and edit the above code sample from JSBin.

If you test out the code again below you'll notice that once you've filled in the textbox and click enter then the behavior will continue as we expected.



Alternate Solutions


The above solution shows how you can use the $.proxy() method to solve the problem, but technically you could have used a plain JavaScript technique instead. By using the .call() or .apply() methods in JavaScript you can control what the value of the this parameter will be just like we did with the $.proxy() method.

The following code snippet shows how you can use the .call() method to control the this parameter.


In a very similar way the next snippet of code shows how you can use the .apply() method as an alternate solution.

NOTE: While the syntax of this function is almost identical to that of call(), the fundamental difference is that call() accepts an argument list, while apply() accepts a single array of arguments. -- https://developer.mozilla.org/...


You can view, run, and edit the above code sample from jsFiddle.

Conclusion


The key concept to remember here is that if you ever need to control the value of the pseudo this paramater inside an event handlers, then you can use the $.proxy() method in jQuery. In addition, you could just use the .call() or .apply() methods in JavaScript if you would rather not use the $.proxy() method.

Until next time...

No comments:

Post a Comment