I wrote the function below to get the length of a listbox
with the id courselessons
. The problem is that when I comment the alert()
the function changecheckbox
works only once.
If I remove the alert
it works fine. But I don't want to have an alert on every single click.
The selOpts
shows correct content only for the first time.
function changecheckbox() {
//alert("function called...");
var selOpts = document.getElementById("courselessons").length();
alert(selOpts);
if (selOpts > 0) {
$('#taskassignment').prop('disabled', false);
}
else {
$('#taskassignment').prop('disabled', true).prop("checked", false);
}
}
function addItem() {
if (seltask == undefined || seltask.length === 0) {
return;
}
var lessonsDropdown = $('#courselessons');
lessonsDropdown.empty();
$("#tasks option:selected").appendTo("#coursetasks");
$("#coursetasks option").attr("selected", false);
if (seltask.length > 0) {
cacheToken = new Date().getTime();
// retrieve data using a Url.Action() to construct url
$.getJSON('@Url.Action("AddTaskToCourse")', {
task: seltask,
lesson: lesson,
_: cacheToken
});
$.getJSON('@Url.Action("UpdateLessonInCourse")', {
_: cacheToken
}).done(function (data) {
//re-enable tasks drop down
//for each returned tasks
$.each(data, function (i, lessons) {
//Create new option
var test = $('<option />').html(lessons);
//append tasks taskss drop down
lessonsDropdown.append(test);
});
seltask = null;
});
}
changecheckbox();
}
<button type="button" id="btnAdd" onclick="addItem(); changecheckbox();">Add Item</button>
The code inside addItem()
is making a GET
request to a resource asynchronously
. This means the code which comes after this function to be execute will not wait for its execution to get complete.
When I uncomment the alert it works fine.
That is because as the alert()
is built in, it halts the execution of script until user interaction. This gave the time addItem()
needs and everything seems to work.
Fortunately, there are solutions available to handle this situation.
Under the covers, $.getJSON
is shorthand for making a GET
request using ajax
with datatype = 'json'
and it returns a promise object which basically tells that please wait honey, i will give you something which could be a success or a failure but sometime later.
So yes, you can easily call the function inside the done()
.
NOTE: These things have been explained pretty well on web so i will not reinvent the wheel :)
Keeping the things simple...
function addItem() {
// Rest of the code...
if (seltask.length > 0) {
cacheToken = new Date().getTime();
// retrieve data using a Url.Action() to construct url
$.getJSON('@Url.Action("AddTaskToCourse")', {
task: seltask,
lesson: lesson,
_: cacheToken
});
$.getJSON('@Url.Action("UpdateLessonInCourse")', {
_: cacheToken
}).done(function (data) {
//re-enable tasks drop down
//for each returned tasks
$.each(data, function (i, lessons) {
//Create new option
var test = $('<option />').html(lessons);
//append tasks taskss drop down
lessonsDropdown.append(test);
});
seltask = null;
changecheckbox();
});
}
}
After this setup, you should remove the changecheckbox()
call from the button onclick
otherwise it would make it execute twice.