"this."refers to a different object in an ajax callback handler

2 views
Skip to first unread message

tan...@gmail.com

unread,
Jan 12, 2007, 9:07:15 AM1/12/07
to Ruby on Rails: Spinoffs
Hello,

I am experiencing some difficulties using prototype 1.4 and i hope
someone here can help me. I've tried a quick google, but to no avail
(hard to search for "this." ;)

My situation: i am writing a form which will have a number of widgets
of various types. I am working on a given widget (itself composed of
several html inputs of different kinds). I have defined a js object
(using prototype's myobj = Class.create followed by myobj.prototype =
blah blah). The various event handlers for the different widget
component parts (i.e. the html fields that make up this widget) are
defined as methods of myobj and assigned to the correct form fields in
myobj's constructor using the bindAsEventListener function. This way i
can reuse the widget several times on the same page, i just create a
new instance of the object and that instance will bind to the correct
fields based on the constructor argument passed. So far, so good, all
working fine.

Now for the problem: i need to get some values from the server and
alter/populate one of the widget components. I define a method which
creates an Ajax.Request, and another method to act as the callback
handler. I hook them up together, and the callback handler gets called
by the Ajax.Request.

Here's the problem: the value of "this."in the callback handler is not
the same as the value of "this."in the other methods of my object - it
looks to me like the value has been "hijacked" and now refers to the
ajax request?

Here's a short example of pseudo-code in case i'm not being clear:

---start ---
var myobj = Class.create();

myobj.prototype = {
/*
* ctor
*/
initialize: function(fieldName) {
//find all the widget components (they're
//all called "something" + fieldName, and
//bind event listeners, etc
this.widgetcomponent = $('something_' + fieldName);
},

/*
* function to get data via ajax
*/
getDataViaAjax: function(){
var params = {
//my params
};
var myAjax = new Ajax.Request(
//my endpoint
{
method:'post',
parameters:$H(params).toQueryString(),
onComplete:this.ajaxCallBackHandler,
});
},

/*
* callback functions for the ajax
*/
ajaxCallBackHandler: function(requestObj,respData){
this.widgetcomponent.value = respData; //ERROR HERE
//basically, "this." seems to refer to the Ajax.Request,
//NOT the instance of the object....
}
}
--- end ---

Nicolas Terray

unread,
Jan 12, 2007, 9:16:46 AM1/12/07
to rubyonrail...@googlegroups.com
On 1/12/07, tan...@gmail.com <tan...@gmail.com> wrote:
> Here's the problem: the value of "this."in the callback handler is not
> the same as the value of "this."in the other methods of my object - it
> looks to me like the value has been "hijacked" and now refers to the
> ajax request?
>

Hi,

Please try to replace this line :
> onComplete:this.ajaxCallBackHandler,
by this one :
> onComplete:this.ajaxCallBackHandler.bind(this),

HTH,
Nicolas Terray

tanguyr

unread,
Jan 12, 2007, 9:35:15 AM1/12/07
to rubyonrail...@googlegroups.com
Brilliant!

thanks vey much. I had worked out a hack using a closure, but this (no
pun intended) is *much* more elegant.

Thanks again Nicolas.

Regards,
/t

Chris Lear

unread,
Jan 12, 2007, 10:17:38 AM1/12/07
to rubyonrail...@googlegroups.com
* tanguyr wrote (12/01/07 14:35):

> Brilliant!
>
> thanks vey much. I had worked out a hack using a closure, but this (no
> pun intended) is *much* more elegant.

This much more elegant thing is still a closure. The reason your closure
looks like a hack in comparison to this elegant solution is that the
prototype author(s) just do it a bit better :-) I find this is often the
case when comparing my code to Prototype code.

tanguyr

unread,
Jan 12, 2007, 10:41:41 AM1/12/07
to rubyonrail...@googlegroups.com
well, when it comes to frameworks, i'm a fan of swimming with the
current... if this is the "prototype way" to do it then so be it.

Now (*ahem*) i also noticed that "this." gets hijacked inside
iterators (each, find, etc). Oh mighty prototype masters, enlighten
this poor seeker after knowledge...

Nicolas Terray

unread,
Jan 12, 2007, 10:49:57 AM1/12/07
to rubyonrail...@googlegroups.com
On 1/12/07, tanguyr <tan...@gmail.com> wrote:
> Now (*ahem*) i also noticed that "this." gets hijacked inside
> iterators (each, find, etc).

... and also in Event.observe, where you have to bindAsEventListener() :)

Some documentation:
http://blog.livollmers.net/?p=17
http://particletree.com/notebook/prototype-and-the-this-keyword/

Yours,
Nicolas Terray

Eric Harrison

unread,
Jan 12, 2007, 1:17:35 PM1/12/07
to rubyonrail...@googlegroups.com
.bind is available to every function via Function.prototype. Any
situation in which you want 'this' to be specifically set to your
object, bind() it to the function and have a nice day... :D

-E

On 1/12/07, Nicolas Terray <nicolas...@gmail.com> wrote:
>


--
Eric Ryan Harrison

tanguyr

unread,
Jan 15, 2007, 7:18:09 AM1/15/07
to rubyonrail...@googlegroups.com
Nicolas,

Thank you very much for those links. It's all becoming clearer, bit by bit...

Regs,
/t

On 1/12/07, Nicolas Terray <nicolas...@gmail.com> wrote:
>

Reply all
Reply to author
Forward
0 new messages