Reputation: 1107
I have a javascript class that has a method that uses jQuery to send an Ajax request and handle the response.
The problem I am having is that I can't figure out how to get the properties of the initial, parent class from within the jQuery functions. I have tried $(this).parent()
but this doesn't get what I need for some reason.
My code is below. Can anyone tell me how to get to the base class from this loop?
function companiesPage()
{
this.childCategoriesSelectid = '#childCategoryid';
this.setChildCategories = function()
{
$.ajax({
url: this.url,
dataType: 'json',
success: function(data)
{
$.each(data.childCategories, function()
{
$($(this).parent().childCategoriesSelectid)//problem here
.append(
$('<option></option>')
.attr('value', this.childCategoryid)
.text(this.name)
);
});
}
});
}
}
Upvotes: 1
Views: 2587
Reputation: 105019
this
before asynchronous Ajax callAjax success handler is asynchronously executed hence looses its callee context (or scope). You have to capture this
free variable and use captured variable within function closure.
this
to have two meanings$(this).parent()...
you're expecting this
to be some HTMLDOMElement
this.name
you're expecting this
to be an object item in your data
(likely array).It becomes obvious that companiesPage is your class (should be Pascal cased and not camel cased). Hence the use of this
within. You likely create it by:
var obj = new CompaniesPage();
obj.setChildCategories();
your code should then look like this:
var CompaniesPage = function()
{
// keep this as public object property
this.childCategoriesSelectId = "#childCategoryid";
// keep this as public object method
this.setChildCategories = function() {
// private reference to object instance for later reuse
var me = this;
$.ajax({
url: this.url, // not sure where this one's coming from
dataType: 'json',
success: function(data) {
$.each(data.childCategories, function() {
$(me.childCategoriesSelectId).append(
$('<option></option>')
.attr('value', this.childCategoryid)
.text(this.name)
);
});
}
});
}
};
You also have to realise that the way that you've defined your class-level method is not memory efficient because individual object instances won't share the same method but would rather have each their own which reflects on memory resources especially when you'd create several instances of the same class.
This is an optimised version of your class:
var CompaniesPage = function() {
// keep this as public object property
this.childCategoriesSelectId = "#childCategoryid";
}
CompaniesPage.prototype.setChildCategories = function() {
// private reference to me as object instance
var me = this;
$.ajax({
url: this.url, // not sure where this one's coming from
dataType: 'json',
success: function(data) {
$.each(data.childCategories, function() {
$(me.childCategoriesSelectId).append(
$('<option></option>')
.attr('value', this.childCategoryid)
.text(this.name)
);
});
}
});
};
Upvotes: 1
Reputation: 70139
parent()
is for DOM traversal. What you have is a scoping problem.
The this
keyword does not always references the same object when entering a new function scope. That is the case when using jQuery's .each()
method which will set this
to the object/element being iterated.
Looks like you're using a constructor-instance pattern, so you just have store a reference to the original object that the this
keyword referenced to (the instance) through a var declaration. This reference will remain unchangeable in the scope chain:
function companiesPage()
{
var _this = this; //stores a reference to this instance object
this.childCategoriesSelectid = '#childCategoryid';
this.setChildCategories = function()
{
$.ajax({
url: this.url,
dataType: 'json',
success: function(data)
{
$.each(data.childCategories, function()
{
$(_this.childCategoriesSelectid) //NO problem here :)
.append(
$('<option></option>')
.val(this.childCategoryid)
.text(this.name)
);
});
}
});
}
}
This way you will be able to access any of your instance's public methods and properties anywhere inside of your instance.
ps. Instanceables/Constructors usually have the first letter upper-cased, by convention.
Upvotes: 2