I have a dropdown of countries and have a jquery ajax call that populates a dropdown with the names of the countries. The problem is that I need to know when the call is complete before I can determine which country is selected. That is, any function I call after the function with the ajax call is called too soon (before the dropdown list is populated), so the following function will crash. I also do NOT want to use async=false (because that will cause more problems and is bad practice). What is the correct way to achieve this?
Here is a general purpose ajax function to retrieve data and populate a select dropdown (ddl) of a specific type with a parameter id:
function RetrieveDD(ddl, ddtype, id) {
var servicename;
switch (ddtype) {
case 'country':
servicename = "LoadCountries";
break;
case 'state':
servicename = "LoadStateProvinces";
break;
case 'city':
servicename = "LoadCityLocalities";
break;
default:
servicename = "";
}
if (servicename != "") {
$.ajax({
url: 'DDService.asmx/' + servicename,
dataType: 'json',
method: 'post',
data: { ID: id },
success: function (data) {
ddl.empty();
$.each(data, function (index) {
ddl.append($("<option" + (index == 0 ? " selected" : "") + "></option>").val(this['V']).html(this['T']));
});
},
error: function (err) {
console.log('Error (RetrieveDD): ' + JSON.stringify(err, null, 2));
}
});
};
};
I have a test button that executes this and want to get the value of a selected option (which will make a call to populate the states, get the value of the first selected state and call again to populate cities). Problem is pretty obvious: I can't say populate the next dropdown without knowing the selected value of the previous one (so I MUST have a way to WAIT for the dropdown to populate FIRST).
$('#btnTest').click(function () {
RetrieveDD($("#ddlCountries"), "country", 0);
var cid = $("#ddlCountries").val(); //this is still undefined because ajax call above not completed
alert("cid = " + cid); //normally another call would be made here to populate the states
});
When clicking the button, you immediately see an alert box popup (with no value for cid) and the countries dropdown is not populated until after you click the [Okay] button from the alert dialog. It's in the wrong order, basically.
If I add async:false to the ajax routine, you will see the alert with the correct cid displayed, however, as people have posted that you should never use async:false. I wish to avoid this, but not sure how to do this correctly. (In case anyone is wondering, I'm removing all MSAjaxToolkit crap from an older dotnet webforms website and replacing with jQuery ajax - which is much faster, smaller, and easier to fix.)
here's the HTML snippet
<input type="button" id="btnTest" value="Test" /><br />
<div id="dd">
<select id="ddlCountries"></select><br />
<select id="ddlStates"></select><br />
<select id="ddlCities"></select>
</div>
************** in response to why I believe this not to be a duplicate ********* Needed to add the requirement for older IE support (which comes with Windows 7, 8, 8.1 and some server versions). IE doesn't support arrow functions or promises (or most ECMA methods after 2015) so a lot of recommended answers, while excellent, did not include code for such. I will try and figure this out and post here.