The selectize dropdown I have on the page gets populated from an AJAX call via the following. What's not working is I need to run some additional code right after the callback() method invocation, but it never continues into the rest of the callback. For instance, the following in the success callback doesn't run the additional code identified:
var $ddl = $("#ContactID");
var control = $ddl[0].selectize;
control.load(function () {
$.ajax({
url: "validURL",
type: "post",
dataType: "json",
data: {
id: recordID
},
error: function () {
alert("Error retrieving data");
callback();
},
success: function (result) {
callback(result.data);
//Does not get called below
loadAdditionalInformation(recordID);
}
});
});
However, if I do this, it works:
success: function (result) {
window.setTimeout(function() {
callback(result.data);
}, 0);
loadAdditionalInformation(recordID);
}
I need to call a method at the point the list is loaded, so I am not sure I want to continue with that, so why is the success callback aborting after the callback() method call.
load expects two parameters, query and callback.
$('#ContactID').selectize({
....
load : function (query, callback) {
$.ajax({
....
success : function(res) {
callback(res.data);
doOtherThings(res);
}
});
}
});
Your code does not pass any of those parameters, so it is very likely that when success() is called, the callback() function is undefined.
I suggest put breakpoint and inspect it.
Related
So this function getXmlData() get's called across the app who's main responsibility is to return xml to and save it to a variable, in this example below it is 'test'
var test = getXmlData();
function getXmlData() {
queryData(getData);
}
function getData(xml) {
if (xml) {
return xml;
}
}
function queryData(callback){
$.ajax({
url: "/echo/JSON",
type: 'POST',
success: function(xml){
callback(xml);
},
error: function(){
console.log("Error!!");
}
})
}
Now we know that here parent function will return before the callback is executed and so 'test' variable will be undefined.
I'm not sure how can I handle this situation here. I'm tied to using this structure. I basically want getXmlData to return xml that is being returned in queryData. Suggestions!?
Struggling to return a AJAX Result Variable back to JavaScript
Note that the $.ajax call below is synchronous (async: false).
Ajax Call
function getState(callback) {
$.ajax({
url: 'getSearchState.php',
data: { "state": callback },
type: 'GET',
async: false,
success: function(result){
alert(result);
},
error: function(result) {
alert(result);
}
});
}
Ajax PHP
<?php
// Database Setup and Query
while ($row = $xxxxx->fetch(PDO::FETCH_ASSOC)) {
$StateVal = $row['State'];
}
return $StateVal;
?>
Javascript Calling the Function
var URL = District.trim();
var StateURL = getState(URL);
It gets the URL vairable from the function just fine, but doesnt return anything.
Any help would be great!
There are problems with that code both client-side and server-side.
Client-side:
Your getState is never returning anything, so it's no surprise that you don't see anything other than undefined for StateURL.
Don't use synchronous ajax. It makes for horrible UX. But if you really, really want to keep using it, here's how you would:
function getState(state) {
var result; // <=== Where we'll put our result
$.ajax({
url: 'getSearchState.php',
data: {"state": state},
type: 'GET',
async: false,
success: function(data) {
// Remember the result;
result = data;
},
error: function() {
result = /*...whatever you want to use to signal an error */;
}
});
// Return the result
return result;
}
Note that I changed the name of the argument to state, since it's not a callback.
But again, don't use synchronous ajax. Instead, use a callback or promises.
Promise: $.ajax already returns a promise, so just return that directly:
function getState(state) {
var result; // <=== Where we'll put our result
$.ajax({
url: 'getSearchState.php',
data: {"state": state},
type: 'GET',
async: false,
success: function(data) {
// Remember the result;
result = data;
},
error: function() {
result = /*...whatever you want to use to signal an error */;
}
});
// Return the result
return result;
}
Note that I changed the name of the argument to state, since it's not a callback.
But again, don't use synchronous ajax. Instead, use a callback or promises.
Promise:
function getState(state) {
return $.ajax({
url: 'getSearchState.php',
data: {"state": state},
type: 'GET'
});
}
Usage:
getState(URL)
.done(function(StateURL) {
// Use it
})
.fail(function() {
// Failed
});
Callback:
function getState(state, callback) {
$.ajax({
url: 'getSearchState.php',
data: {"state": state},
type: 'GET',
success: function(data) {
// Call the callbback with the result
callback(data);
},
error: function() {
// Call the callback with an error
callback(/*...whatever you want to use tosignal an error */);
}
});
}
Usage:
getState(URL, function(StateURL) {
// Use it, check for error
});
Server-side:
As RiggsFolly pointed out, you're returning a string from your PHP code. But that won't output it. To use it client-side, you need to output it (e.g., echo and similar). And to make it easily consumed by the JavaScript, you probably want to json_encode it to ensure that it's in a format JavaScript can understand:
echo json_encode($stateVal);
Then in your success (or done) function, use JSON.parse on it:
result = JSON.parse(data);
this is jQuery and in this case you can specify context and in success function set variables on that context.... a bit crude solution but it will works. Also take a look on arrow functions and promises from ES6, it can help you a lot and give you new perspective about whole problem.
And one main thing!! Ajax is async by default so you need somehow notify your StateURL when data will be ready (here again promise at you service)
I need to call onSuccessLogin method from ajax success method, or put response as argument into onSuccessLogin.
Thank you for answers.
submit: function (form) {
$.ajax({
type: "post",
url: "/login",
data: {
login: $(form).find('#login').val(),
password: $(form).find('#password').val(),
deviceType: environmentInfo.browser,
sdkVersion: environmentInfo.browserVersion,
osVersion: environmentInfo.OS
},
success: function(res) {
localStorage.setItem("languagesList", res);
//how to call onSuccessLogin method from here?
},
//Another implementation
// success: this.onSuccessLogin(res), - dosen't work, if I want put response from ajax into this method call
error: this.onErrorLogin
});
},
onSuccessLogin: function () {
//localStorage.setItem("languagesList", res); get response from second implementation
window.location = "/";
}
By creating a reference (that can be seen from the scope of AJAX success callback) to the object holding onSuccessLogin.
Inside the submit method (as a sibling of onSuccessLogin) that object is this.
Also see MDN reference on ES6 Arrow functions - abstraction for binding this to enclosing scope.
submit: function (form) {
var self = this;
$.ajax({
type: "post",
url: "/login",
data: {
login: $(form).find('#login').val(),
password: $(form).find('#password').val(),
deviceType: environmentInfo.browser,
sdkVersion: environmentInfo.browserVersion,
osVersion: environmentInfo.OS
},
success: function(res) {
localStorage.setItem("languagesList", res);
self.onSuccessLogin();
},
//Another implementation
// success: this.onSuccessLogin(res), - dosen't work, if I want put response from ajax into this method call
error: this.onErrorLogin
});
},
onSuccessLogin: function () {
//localStorage.setItem("languagesList", res); get response from second implementation
window.location = "/";
}
I don't know this logic is correct or not , if you place the function outside of ajax loop it will work .
$.ajax({
url: 'test',
success: function(data) {
alert("received contents="+data);
onSuccessLogin();
}
});
function onSuccessLogin() {
alert("Successfully logged!!!");
}
If I have to leverage niceties of jQuery AJAX API and set my own custom settings for each ajax call my app makes like below:
Say I have a page which displays employee information within table by making ajax calls to some API.
define(["jQuery"], function($) {
var infoTable = function (options) {
function init() {
// Provide success callback
options.success_callback = "renderData";
getData();
}
function renderData() {
// This callback function won't be called as it is not
// in global scope and instead $.ajax will try to look
// for function named 'renderData' in global scope.
// How do I pass callbacks defined within requirejs define blocks?
}
function getData() {
$.ajax({
url: options.apiURL,
dataType: options.format,
data: {
format: options.format,
APIKey: options.APIKey,
source: options.source,
sourceData: options.sourceData,
count: options.count,
authMode: options.authMode
},
method: options.method,
jsonpCallback: options.jsonpCallback,
success: options.success_callback,
error: options.error_callback,
timeout: options.timeout
});
}
}
return {
init: init
}
}
How do I achieve this?
I know we can use JSONP request as require calls but that restricts me to using jsonp, making GET requests and all other features $.ajax offers.
This example would let you either use a default success callback, or provide an override, using:
success: options.successCallback || renderData
(The example uses jsfiddle rest URLs - this fact is unimportant, and stripped out the data object to keep the example short)
define("mymodule", ["jquery"], function($) {
function renderData() {
console.log("inside callback");
}
function getData(options) {
$.ajax({
url: options.apiURL,
dataType: options.format,
method: options.method,
jsonpCallback: options.jsonpCallback,
success: options.successCallback || renderData,
error: null,
timeout: options.timeout
});
}
return {
getData: getData
}
});
require(["mymodule"], function(m) {
console.log(m, m.getData({
apiURL: "/echo/json/"
}));
console.log(m, m.getData({
successCallback: function() { console.log("outside callback"); },
apiURL: "/echo/json/"
}));
});
Would print:
GET http://fiddle.jshell.net/echo/json/ 200 OK 263ms
Object { getData=getData()} undefined
GET http://fiddle.jshell.net/echo/json/ 200 OK 160ms
Object { getData=getData()} undefined
inside callback
outside callback
The title is a bit weird, don't quite know the best way to explain it in a sentence...
At present there is an object with 3 functions; func, funcSuccess, and funcFailure. func contains a jQuery ajax request, with this.funcSuccess as the success callback, and funcError as the error callback. func is passed a callback for any success values to be passed back to, however this callback needs to be executed in the funcSuccess code.
Here's the code:
var Obj =
{ func: function (callback) {
$.ajax(
{ type: 'POST'
, url: '/func'
, success: this.funcSuccess
, error: this.funcError
}
)
}
, funcSuccess: function (res) {
// THIS IS WHERE CALLBACK IS NEEDED
callback(res.thing)
}
, funcError: function (res) {
debug(res)
}
}
I'm wondering if there's a tidier way to do it rather than having:
var that = this
$.ajax(
{ type: 'POST'
, url: '/func'
, success: function (res) {
that.funcSuccess(res)
}
, error: this.funcError
}
)
Pretty sure I'm missing something obvious, just not quite with it today...
What about storing the callback explicitly in your object, so you don't have to worry about closure scopes:
var Obj =
{ func: function (callback) {
//this.callback = callback;
$.ajax(
{ type: 'POST'
, url: '/func'
, success: $.proxy(this.funcSuccess, this, callback)
, error: $.proxy(this.funcError, this)
}
)
}
, funcSuccess: function (callback, res) {
callback(res.thing)
}
, funcError: function (res) {
debug(res)
}
}
Edit: I forgot to bind the callbacks to this. In JQuery you can do it with $.proxy, see changes above.
Edit: A further tidy (jQuery 1.6 allows for this) with passing the callback as an argument to $.proxy, so no need to attach it to the current object.
You need to pass the callback into the funcSucess, else it won't have access to it. Here by using a closure:
var Obj = {
func: function (callback) {
return $.ajax({
type: 'POST',
url: '/func',
success: this.makeFuncSuccess(callback),
error: this.funcError
});
}, makeFuncSuccess(callback) {
return function funcSuccess (res) {
callback(res.thing);
};
},
funcError: function (res) {
debug(res)
}
};