Reputation: 1405
I want to execute a callback function inside an object. I don't know if there is something wrong in the way I'm doing this.
I've googled for a solution, also searched on stackoverflow but couldn't find anything similar to the way I'm coding this.
PHPGateway.js
var PHPGateway = {
opt_friendlyURL: true,
opt_folder: 'ajax/',
callback_function: null,
useFriendlyURL: function (bool) {
this.opt_friendlyURL = bool;
},
setFolder: function (folder) {
this.opt_folder = folder;
},
send: function (service, method, data, callback) {
var url,
json_data = {};
if (this.opt_friendlyURL) {
url = this.opt_folder + service + '/' + method;
} else {
url = this.opt_folder + 'gateway.php?c=' + service + '&m=' + method;
}
if (data != undefined) {
json_data = JSON.stringify(data);
}
this.callback_function = (callback == undefined) ? null : callback;
$.ajax({
method: 'POST',
url: url,
data: {data: json_data},
success: this.ajax_success,
error: this.ajax_error
});
},
ajax_success: function (returned_object) {
if (this.callback_function != null) {
this.callback_function(returned_object.error, returned_object.data);
}
},
ajax_error: function () {
this.callback_function.call(false, {});
}
};
Then inside the HTML file that loads PHPGateway.js, I've the following code:
<script>
function submit_handler(event) {
event.preventDefault();
form_submit();
}
function form_callback(error, data) {
if(error == null) {
alert(data.text);
}
}
function form_submit() {
var data = {
status: $('#inStatus').val(),
amount: $('#inAmount').val(),
id: $('#inBudgetID'). val()
}
PHPGateway.send('budget', 'status', data, form_callback);
}
$('form').one('submit', submit_handler);
</script>
I get an error on this.callback_function(returned_object.error, returned_object.data);
, the error is Uncaught TypeError: Object # has no method 'callback_function'.
Thank You!
Based on minitech answer, I've updated PHPGateway.js like this. I've omitted the parts that weren't updated.
var PHPGateway = {
// Omitted code
send: function (service, method, data, callback) {
var url,
json_data = {},
that = this;
if (this.opt_friendlyURL) {
url = this.opt_folder + service + '/' + method;
} else {
url = this.opt_folder + 'gateway.php?c=' + service + '&m=' + method;
}
if (data != undefined) {
json_data = JSON.stringify(data);
}
this.callback_function = (callback == undefined) ? null : callback;
$.ajax({
method: 'POST',
url: url,
data: {data: json_data},
success: function(data, textStatus, jqXHR) {
that.ajax_success(data, textStatus, jqXHR);
},
error: function(jqXHR, textStatus, errorThrown) {
that.ajax_error(jqXHR, textStatus, errorThrown);
}
});
},
ajax_success: function (data, textStatus, jqXHR) {
if (this.callback_function != null) {
this.callback_function(true, data.data);
}
},
ajax_error: function (jqXHR, textStatus, errorThrown) {
this.callback_function.call(false, {});
}
};
Now it works!!!
Upvotes: 0
Views: 1544
Reputation: 18888
In your call to $.ajax, you need to add a context
option:
$.ajax({
method: 'POST',
url: url,
data: {data: json_data},
context: this,
success: this.ajax_success,
error: this.ajax_error
});
Your this
variable in your Ajax success and error handlers are not pointing to the object you think they are. The context
option to $.ajax() sets which object this
points to in the Ajax callbacks.
Upvotes: 2
Reputation: 225263
Here’s your problem:
$.ajax({
method: 'POST',
url: url,
data: {data: json_data},
success: this.ajax_success,
error: this.ajax_error
});
When you set success
and error
to methods on this
, they don’t keep their this
. When a JavaScript function is called, it gets bound a this
:
someFunction(); // this is undefined or the global object, depending on strict
someObject.someFunction(); // this is someObject
The built-in .call
, .apply
, and .bind
of Function
objects help you override this.
In your case, I think jQuery binds this
to the Ajax object – a good reason to both not use jQuery and always use strict mode.
If you can guarantee or shim ES5 support, bind
is an easy fix:
$.ajax({
method: 'POST',
url: url,
data: {data: json_data},
success: this.ajax_success.bind(this),
error: this.ajax_error.bind(this)
});
Which is equivalent to this if you can’t:
var that = this;
$.ajax({
method: 'POST',
url: url,
data: {data: json_data},
success: function() {
that.ajax_success.apply(that, arguments);
},
error: function() {
that.ajax_error.apply(that, arguments);
}
});
And now, a tip for you: don’t namespace, and if you do, don’t use this
. this
is great for objects that are meant to be constructed. What would seem more appropriate is something like this, if you really have to:
var PHPGateway = (function() {
var callbackFunction;
var options = {
friendlyURL: true,
…
};
…
function send(service, method, data, callback) {
…
}
…
return { send: send };
})();
Upvotes: 1