EDIT: The base question is the same, but instead of a global buttons array getting passed back, I'm now passing back a getButtons() function.
I'm making an AJAX request to the server to get data to populate a popup box, and it's passing the data back as a JSP. Part of the JSP includes a JSON object with data used by the client to draw some buttons.
The issue is that sometimes the JSON object isn't ready on the success callback, so the buttons don't get drawn. The rest of the JSP is there, so the ancillary functionality works fine.
For most pages this does work flawlessly, but on certain pages, where the content is ready much more quickly, the buttons haven't yet been set. How can I ensure that buttons will be set?
Server code:
//Arbitrary JSP code prior to this function
function getButtons() {
var buttons = [];
buttons.push(addButton('Send', 'functionName', buttonDescription));
buttons.push(addButton('Cancel', 'functionName', buttonDescription));
return buttons;
}
Client code:
popupBoxFunction(action, params, global) {
$.ajax({
url: action,
type: 'POST',
data: params,
dataType: 'html',
global: global,
success: function (data, textStatus, xhr) {
$("#container").html(data);
if (typeof getButtons() != "undefined") {
var myButtons = generatePopupButton(getButtons());
for (var i = 0; i < myButtons.length; i++) {
//do something
}
}
//arbitrary rest of function
}
If you want your generatePopupButton
to be called only after all the buttons are available, why don't we just call it inside getButtons
. That way you don't have to check if buttons are available and everything happens one after the other.
Your JSP :
<script>
// make it an IIFE so that it's executed right after parsing
(function() {
var buttons = [];
buttons.push(addButton('Send', 'functionName', buttonDescription));
buttons.push(addButton('Cancel', 'functionName', buttonDescription));
var myButtons = generatePopupButton(buttons);
for (var i = 0; i < myButtons.length; i++) {
//do something
}
})();
</script>
Your Client Code :-
popupBoxFunction(action, params, global) {
$.ajax({
url: action,
type: 'POST',
data: params,
dataType: 'html',
global: global,
success: function (data, textStatus, xhr) {
/* just add your html and script to DOM
and wait for the browser to execute it for you */
$("#container").html(data);
}
});
//arbitrary rest of function
}
If you don't like the idea of moving your generatePopupButton
and other script code in to your JSP, you can make use of Function Body As a String
technique used in most of the template engines.
In your JSP :-
<!-- make sure type is not text/javascript, something gibberish that
is not known to browser -->
<script id="template" type="my-type">
var buttons = [];
buttons.push(addButton('Send', 'functionName', buttonDescription));
buttons.push(addButton('Cancel', 'functionName', buttonDescription));
return buttons;
</script>
Make sure that script
type is not something that is known to browser. You can even change the script
tag to div
tag if you please :)
In your client code :-
$.ajax({
url: action,
type: 'POST',
data: params,
dataType: 'html',
global: global,
success: function (data, textStatus, xhr) {
$("#container").html(data);
var funBody = $('#template').html();
/* Now that we've function body as text
retrieve that in code*/
var fn = new Function(funBody);
// Now that we've the function invoke it to get buttons
var myButtons = generatePopupButton(fn());
for (var i = 0; i < myButtons.length; i++) {
//do something
}
}
});
Here's a bin to play with the second approach.
There are even other ways of doing this, but these two are just from the top of my head :)
According to me the best way would be to move the code where html
is set $("#container").html(html)
, inside the IF
statement so that html
is rendered only after the buttons are set.
EDIT
As rendering HTML and BUTTON are independent. A minimum amount of delay can be introduced before rendering the HTML so that difference between rendering HTML and rendering buttons gets reduced.
function popupBoxFunction(action, params, global) {
var ajaxPromise = $.ajax({
url: action,
type: 'POST',
data: params,
dataType: 'html',
global: global
});
}
promiseAjax.done(function(html){
setTimeout(function(html) {
$("#container").html(html);
}, 300);
if (typeof getButtons() != "undefined") {
var myButtons = generatePopupButton(getButtons());
for (var i = 0; i < myButtons.length; i++) {
//do something
}
// $("#container").html(html);
}
});
Could you please allow some milliseconds to pass before checking if (typeof getButtons() != "undefined") {
.
For example inside success handler can you please try something like following:
success: function (data, textStatus, xhr) { $("#container").html(data); setTimeout(function(){ if (typeof getButtons() != "undefined") { var myButtons = generatePopupButton(getButtons()); for (var i = 0; i < myButtons.length; i++) { //do something }// end for loop } //end if check },500); //500 milli sec delay }// end success handler
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.