Reputation: 36393
I have a very simple class, but already run into pain with the definition of ‘this’ in Typescript:
Typescript
/// <reference path='jquery.d.ts' />
/// <reference path='bootstrap.d.ts' />
module Problem {
export class Index {
detailsUrl: string;
constructor() {
$('.problem-detail-button').click((e) => {
e.preventDefault();
var $row = $(this).closest('tr'); //this must be that of the callback
var problemId: number = $row.data('problem-id');
$.ajax({
url: this.detailsUrl, //this must be the instance of the class
data: { id: problemId },
type: 'POST',
success: (result) => {
$('#details-modal-placeholder').html(result);
$('#details-modal-placeholder modal').modal('show');
},
})
});
}
}
}
Javascript
var Problem;
(function (Problem) {
var Index = (function () {
function Index() {
var _this = this;
$('.problem-detail-button').click(function (e) {
e.preventDefault();
var $row = $(_this).closest('tr');
var problemId = $row.data('problem-id');
$.ajax({
url: _this.detailsUrl,
data: {
id: problemId
},
type: 'POST',
success: function (result) {
$('#details-modal-placeholder').html(result);
$('#details-modal-placeholder modal').modal('show');
}
});
});
}
return Index;
})();
Problem.Index = Index;
})(Problem || (Problem = {}));
Now the problem is that the line
var $row = $(this).closest('tr'); //this must be that of the callback
and this line
this.detailsUrl, //this must be the instance of the class
conflict in the meaning of 'this'
How do you handle the mixture of the 'this'?
Upvotes: 16
Views: 12073
Reputation: 11294
module Problem {
export class Index {
detailsUrl: string;
constructor() {
var that = this;
$('.problem-detail-button').click(function (e) {
e.preventDefault();
var $row = $(this).closest('tr'); //this must be that of the callback
var problemId: number = $row.data('problem-id');
$.ajax({
url: that.detailsUrl, //this must be the instance of the class
data: { id: problemId },
type: 'POST',
success: (result) => {
$('#details-modal-placeholder').html(result);
$('#details-modal-placeholder modal').modal('show');
},
})
});
}
}
}
Explicitly declare that = this
so you have a reference for that.detailsUrl
, then
don't use a fat arrow for the click handler, so you get the correct this
scope for the callback.
Upvotes: 16
Reputation: 71
module Problem {
export class Index {
constructor() {
$('.classname').on('click',$.proxy(this.yourfunction,this));
}
private yourfunction(event){
console.log(this);//now this is not dom element but Index
}
}
}
check about jquery.proxy(). just remind you there is another way.
Upvotes: 0
Reputation: 2468
Late to the thread, but I have something different to suggestion.
Instead of:
var $row = $(this).closest('tr'); //this must be that of the callback
Consider using:
var $row = $(e.currentTarget).closest('tr');
As in this example, anywhere you might want to use this
in a jQuery callback, you have access to a function parameter you can use instead. I would suggest that using these parameters instead of this
is cleaner (where "cleaner" is defined as more expressive and less likely to be turned into a bug during future maintenance).
Upvotes: 0
Reputation:
If you're only supporting browsers that have .addEventListener
, I'd suggest using that to associate your data with your elements.
Instead of implementing your code, I'll just give a simple example.
function MyClass(el) {
this.el = el;
this.foo = "bar";
el.addEventListener("click", this, false);
}
MyClass.prototype.handleEvent = function(event) {
this[event.type] && this[event.type](event);
};
MyClass.prototype.click = function(event) {
// Here you have access to the data object
console.log(this.foo); // "bar"
// ...and therefore the element that you stored
console.log(this.el.nodeName); // "DIV"
// ...or you could use `event.currentElement` to get the bound element
};
So this technique gives you an organized coupling between elements and data.
Even if you need to support old IE, you can shim it using .attachEvent()
.
So then to use it, you just pass the element to the constructor when setting up the data.
new MyClass(document.body);
If all the logic is in your handler(s), you don't even need to keep a reference to the object you created, since the handlers automatically get it via this
.
Upvotes: 2
Reputation: 276189
You need to fallback to the standard way of javascript. i.e store the variable as :
var self = this;
Then you can use function
instead of ()=>
and use this
to access variable in callback and self
to access the instance of the class.
Here is the complete code sample:
module Problem {
export class Index {
detailsUrl: string;
constructor() {
var self = this;
$('.problem-detail-button').click(function(e){
e.preventDefault();
var $row = $(this).closest('tr'); //this must be that of the callback
var problemId: number = $row.data('problem-id');
$.ajax({
url: self.detailsUrl, //this must be the instance of the class
data: { id: problemId },
type: 'POST',
success: (result) => {
$('#details-modal-placeholder').html(result);
$('#details-modal-placeholder modal').modal('show');
},
})
});
}
}
}
// Creating
var foo:any = {};
foo.x = 3;
foo.y='123';
var jsonString = JSON.stringify(foo);
alert(jsonString);
// Reading
interface Bar{
x:number;
y?:string;
}
var baz:Bar = JSON.parse(jsonString);
alert(baz.y);
And your generated javascript:
var Problem;
(function (Problem) {
var Index = (function () {
function Index() {
var self = this;
$('.problem-detail-button').click(function (e) {
e.preventDefault();
var $row = $(this).closest('tr');
var problemId = $row.data('problem-id');
$.ajax({
url: self.detailsUrl,
data: {
id: problemId
},
type: 'POST',
success: function (result) {
$('#details-modal-placeholder').html(result);
$('#details-modal-placeholder modal').modal('show');
}
});
});
}
return Index;
})();
Problem.Index = Index;
})(Problem || (Problem = {}));
var foo = {
};
foo.x = 3;
foo.y = '123';
var jsonString = JSON.stringify(foo);
alert(jsonString);
var baz = JSON.parse(jsonString);
alert(baz.y);
Upvotes: 9
Reputation: 10119
I normally bind this
to a variable as soon as I have it in the scope I want.
However the this
you are after could be found like this:
constructor() {
var class_this=this;
$('.problem-detail-button').click(function (e) {
e.preventDefault();
var callback_this=e.target;
Upvotes: 1