It seems that the kendo unobtrusive-javascript style event is causing break this in my method context.
Say I have a Foo object created as bar = new Foo()
function Foo(){}; Foo.prototype.name = "Herring"; Foo.prototype.doSomething = function(e) { alert(this.name); }; bar = new Foo();
And attach the event using a data click, for example
<a data-role="button" data-click="bar.doSomething">Click Me</a>
Changed the context of the object to bar (not sure why, since we have a convenient container element .), And therefore this.name is undefined.
I tried the old var self = this; in the constructor of the object, but it doesnβt work, does anyone know what is the best way to solve this?
Update: Hacky Workaround
Since I really do not want to lose the benefits of packing my modules as classes, I created wrappers for event-calling functions that then call methods on the corresponding object.
For example, connect markup to a wrapper function.
<a data-role="button" data-click="doSomething">Click Me</a>
and the wrapper function calls the object.method object.
function doSomething(e){ bar.doSomething(e) };
Now this achieves the intended result, but it's pretty terrible, every event called from the markup should have a proxy function , as above. So imagine a scenario in which you have 300 events ... and you will immediately understand why this is terrible.
If there is no other solution, and I really hope that there is. I will send this workaround as an answer, but as far as I know, this is far from desirable.
Footnote
I will be completely honest, this seems like a major architectural flaw in Kendo, since this method of invoking events from markup is the "Kendo path." Obviously, it cannot be fixed, because probably a fair bit of code is already dealing with this as a reference to the html element.
The ability to override it or the ability to route these event calls using a common handler that can pass a call, in essence a common proxy function, are possible solutions to this problem. It can also be a simple custom value for a kendo. object kendo. .
Theoretical solution
I will talk about the next steps, if this works, it is theoretically possible to throw events into a common proxy server and call a function with the correct scope.
Suppose we use the event attribute to call the proxy server, and then create a separate attribute to pass the call to the object / method. For example.
<a data-role="button" data-click="prox" data-prox="o.eventHandler">Click Me</a>
A proxy function would prox from the attribute dataset:
- using eval
Not because I'm evil, but necessary.
// sitting in global namespace function prox(e){ var p = e.sender.element.data['prox']; // make sure our delegate is a function. if("function" == eval("typeof "+p)) { eval(p + "(e)"); } }
Obviously, I need a better way to do this, but at least it's DRY.
(I prepared a non-emergency method in an instant ...)
Start Eval ...
use the window context to search for an object / method.
function prox(e) { var p = e.sender.element.data['prox']; if(p.indexOf(".") == -1){ // global function : where *this* is window. // check you've got the function if not ditch it. if("function" == typeof window[p]) window[p](e); } else { // object/method (one level deep only.) var s = p.split("."); var o = s[0], m = s[1]; // check the object/method is a function before executing it. if("function" == typeof window[o][p]) window[o][p](e); } }
Of course, for global (window) functions with a scope, this as an element is probably more useful, but in this case you have a choice, I would not notice