How to Avoid Multiple Ajax calls - javascript

What I need
when click event is triggered service call is made then it may call only one time only.
Use case
Dropdown1
Dropdown2
Dropdown3
1. There are three dropdown in html page.
2. when dropdown 1 is call - ajax call made only 1 time.
3. when dropwdown 2 is call -ajax call made only 1 time.
4. when dropwdown 3 is call -ajax call made only 1 time.
Now user change dropdown 1.
5. when dropwdown 1 is call -ajax call made only 1 time.
Problem occurs
6. Now when dropwdown 2 is call -ajax call made only 2 time.
7. Now when dropwdown 3 is call -ajax call made only 2 time.
similary when we change dropdown 1
count increase by one.
Now user change dropdown 1.
8. Now when dropwdown 2 is call -ajax call made only 3 time.
9. Now when dropwdown 3 is call -ajax call made only 3 time.
Js code
dowpdown 1 has assigned id with dowpdown_1
dowpdown 2 has assigned id with dowpdown_2
dowpdown 3 has assigned id with dowpdown_3
$("#dowpdown_1").change(function() {
$.ajax({
url: 'path',
cache: false,
data: {
data
},
success: function(html) {
console.log('dowpdown_1');
$("#dowpdown_2").change(function() {
$.ajax({
url: 'path',
cache: false,
data: {
data
},
success: function(html) {
console.log('dowpdown_2');
}
});
}
$("#dowpdown_3").change(function() {
$.ajax({
url: 'path',
cache: false,
data: {
data
},
success: function(html) {
console.log('dowpdown_3');
}
});
});
}
});
});
Any solution is most welcome.

Everytime you change the dropdown_1 you are adding a new event to dropdown_2 and dropdown_3 that do the same thing.
It might seem that this is the same event but you are actually binding new change events to your dropdowns.
You can either bind only once the events or if you want your previous structure (seems like cascade functionality but I am not sure) you could use this:
$("#dowpdown_2").off().on('change', function () {// do the ajax});
$("#dowpdown_3").off().on('change', function () {// do the ajax});
This way everytime you add the new function on the change event you will at least unbind all previous events from it and it won't trigger again. Of course this means that there aren't any other change events that matter to your case because they will be unbinded too.
Else as I said you can just do this
$("#dowpdown_1").on('change', function ()
{
$.ajax({
url: 'path',
cache: false,
data: {data},
success: function (html)
{
console.log('dowpdown_1');
}
});
$("#dowpdown_2").on('change', function () {
$.ajax({
url: 'path',
cache: false,
data: {data},
success: function (html)
{
console.log('dowpdown_2');
}
});
$("#dowpdown_3").on('change', function () {
$.ajax({
url: 'path',
cache: false,
data: {data},
success: function (html)
{
console.log('dowpdown_3');
}
});

everytime your ajax is completed, your callback attaches a new event to your other 2 dropdowns. That means every time you bind an event inside of an ajax callback you have to care if an element exists or it will be new created.
TLDR adding .unbind in front of your event should fix this
$("#dowpdown_2").unbind().change(function () {
....
})

Related

jQuery Click Handler with Called Ajax Sub-Method has a strange delay on $(this).prop('disabled', true) [duplicate]

This question already has answers here:
updated UI not showing before sync ajax call
(2 answers)
Closed 3 years ago.
I have a strange situation where the following Click-Handler (via one() to prevent double-clicks) has a called Ajax method from the inside. The first thing it's supposed to do is to disable my button.
Normally, if I don't have any Ajax inside and just have a simple click handler, this works and disables the button immediately:
$('#button').one('click', function (event) {
$(this).prop('disabled', true);
});
But if I have the following, with a called sub-method which involves Ajax, I notice that the 1st statement (Disable Button) does not occur until the sub-method is complete. But why? The button should get disabled immeditely as the first statement, regardless of how long the Ajax takes to complete.
$('#submitButton').one('click', function (event) {
$(this).prop('disabled', true); // Doesn't get disabled until AFTER submitSurvey()
submitSurvey(); // Call some method that does Ajax
});
function submitSurvey() {
$.ajax({
url: 'surveyProcess',
type: 'post',
processData: false,
contentType: false,
data: formData,
async: false, /* Note async = false, so nothing asynchronous here either */
success: function() {
//...
}
What could be going on here? I just need to disable the button immediately, without any delay.
You can use beforeSend() event for the same use
$('#submitButton').on('click', function (event) {
$.ajax({
url: 'surveyProcess',
type: 'post',
processData: false,
contentType: false,
data: formData,
async: false, /* Note async = false, so nothing asynchronous here either */
beforeSend: function(){
$(this).prop('disabled', true);
},
success: function() {
//...
}
});
});

Fullcalendar updateEvent doesn't rerender

I want to add events to my DB via fullcalendar. So I want to add an event and set its id to the id it gets in my DB.
function addCalEvent(event) {
var jEvent = {};
jEvent['startTime'] = moment(event.start).unix();
jEvent['worker']="GUZ"
jEvent['title']=event.title;
if (event.end) {
jEvent['endTime'] = moment(event.end).unix();
}
$.ajax({
url: 'dux.html',
type: 'POST',
data: {
type: 'addNewEvents',
event: jEvent,
REQUEST_TOKEN: "REQUEST_TOKEN>",
},
datatype: 'json',
success: function(data) {
event.id=data;
event.title="NEW";
$('#calendar').fullCalendar('updateEvent', event);
},
});
}
The ajax retrieves the id of the added event and the id and title do get changed, but the 'updateEvent' method doesn't seem to be called, because there is no change to the rendered events title or id.
Ok,
apperently if you make a asynchronous ajax call the order in which commands are executed isn't the order you write it.
I need to add async: false to make this work.
You can manually call rerender events with $('#calendar').fullCalendar( ‘rerenderEvents’ )
Link to docs here

Can't access object made by ajax call

I have this ajax request:
$.ajax({
type: "POST",
dataType: "json",
data: dataString,
url: "app/changeQuantity",
success: function(data) {
$('#table').append('<tr><td><a id="uid">click</a></td></tr>');
});
as you can see it makes new row in #table. But this new objects made by ajax are not accessible from next functions. Result from ajax is not a regullar part of DOM, or what is the reason for this strange behavior?
$('#uid').on('click', function () {
alert('ok');
});
Use event delegation:
$(document).on('click','#uid', function () {
alert('ok');
});
Note that ajax calls are asynchronous. So whatever you do with the data you need to do it in a callback within the success function (that is the callback which is called when the ajax call returns successfully).
Jquery on doesn't work like that. Use have to give a parent which not loaded by ajax, and the specify ajax load element like this
$('#table').on('click','#uid' ,function () {
// what ever code you like
});
Is simple and complex at the same time. Simple to solve but complex if you are getting started with javascript...
Your event handler - onclick is being fired and bound to an object that doesnt yet exist.
So when you append the object to the #table, you need to set up your click handler as the object now exists.
So in your success part of the ajax return add the click handler event there.
success: function(data) {
$('#table').append('<tr><td><a id="uid">click</a></td></tr>');
$('#uid').on('click', function () {
alert('ok');
});
});
Or how about you make it dynamic and create a function to do it for you.
function bindClick(id) {
$('#' + id).click(function() {
//Do stuff here
console.log('I made it here' + id);
});
}
Then:
success: function(data) {
$('#table').append('<tr><td><a id="uid">click</a></td></tr>');
bindClick(uid);
});
}
This is a super contrived example but you get the idea you just need to make the rest of it dynamic as well. for example some name and counter generated id number: id1, id2, id3...
Try it like this, add this $('#uid').on('click', function () { into the success
$.ajax({
type: "POST",
dataType: "json",
data: dataString,
url: "app/changeQuantity",
success: function(data) {
$('#table').append('<tr><td><a id="uid">click</a></td></tr>');
$('#uid').on('click', function () {
alert('ok');
});
});
});

how to add delay function inside the ajax function

I am using ajax function to update and output the result.
how can I delay like 2 secs before the second update result get display again?
since right now, after the first update and second update, the text is the same like
'updated' I want to let user know this is the second time updated msg.
$.ajax({
type: "post",
url: "function.php",
data: "ajax=updateAward&" + inputs,
success: function(html) {
$('#message_award').html(''); //clear previous text
//delay 2 sec then display below?
$('#message_award').html(html) ;
}
});
Use setTimeout to execute a function after a delay (given in milliseconds). Here's a complete example:
$.ajax({
type: "post",
url: "function.php",
data: "ajax=updateAward&" + inputs,
success: function(html) {
setTimeout(function() {
$('#message_award').html(html);
}, 2000);
}
});

jQuery plugin bsmSelect doesn't update its values when it is called again and its select options have changed

I'm using bsmSelect jQuery plugin. Basically, what it does is changing the way a select-multiple is rendered to make easier to pick up the options. It hides the select element and shows a list instead.
So, first of all I'm applying the plugin function to my select-multiple element:
$(document).ready(function() {
...
$('#my_select_multiple').bsmSelect({
plugins: [$.bsmSelect.plugins.sortable()],
title: 'Add',
removeLabel: 'Remove'
});
...
});
On the other way, I have another select element (this one is simple) which has an ajax request bind to its change event. This ajax request get new #my_select_multiple options depending on the select simple value. Ajax response is the new HTML for #my_select_multiple options. So I have:
function getNewOptions(val) {
var r = $.ajax({
type: 'GET',
url: /*My URL*/
}).responseText;
return r;
}
...
$(document).ready(function() {
...
$('#my_select_simple').change() {
$('#my_select_multiple').html(getNewOptions($(this).val()));
}
...
});
AJAX is working as expected. New options are got correctly and they are inserted into #my_select_multiple (which is hidden by bsmSelect plugin, but I can check it with Firebug). But bsmSelect didn't realize new changes and doesn't get updated.
So, I think what I want is to reapply $('#my_select_multiple').bsmSelect(); with its new options.
I've been looking around a little bit and here is what I have tried.
1. I've tried to call again the funcion with the success and complete (one at time) of the AJAX request. Didn't work:
function getNewOptions(val) {
var r = $.ajax({
type: 'GET',
url: /*My URL*/,
success: function() { $('#my_select_multiple').bsmSelect(); }
}).responseText;
return r;
}
2. I've tried to bind the function with the on jQuery function. Didn't work:
$('#my_select_simple').on('change', function() {
$('#my_select_multiple').bsmSelect();
});
3. I've tried 1 and 2 removing previosly the HTML generated by bsmSelect. Didn't work.
Thank you very much.
UPDATE: The exact code
First I have a global.js file which apply bsmSelect plugin to some select multiples (.quizzes):
$('.quizzes').bsmSelect({
plugins: [$.bsmSelect.plugins.sortable()],
title: 'Add',
removeLabel: 'Remove'
});
And then, in the php file I define the updateQuizzes function and bind it to the select simple (project_id) change event:
<script type="text/javascript">
function updateQuizzes(project_id) {
var r = $.ajax({
type: 'GET',
url: '<?php echo url_for('event/updateQuizzes')?>'+'<?php echo ($form->getObject()->isNew()?'':'?id='.$form->getObject()->getId()).($form->getObject()->isNew()?'?project_id=':'&project_id=')?>'+project_id,
success: function() { $('.quizzes').bsmSelect({
plugins: [$.bsmSelect.plugins.sortable()],
title: 'Add',
removeLabel: 'Remove'
}); }
}).responseText;
return r;
}
$('#project_id').change(function(){
$('.quizzes').html(updateQuizzes($(this).val()));
});
</script>
As I told, the AJAX request works without problems, but not the calling bsmSelect the second time...
Not sure if this is what the problem is, but you could try
$('#my_select_simple').change() {
$('#my_select_multiple').html(getNewOptions($(this).val())).trigger('change');
}
This triggers a change event on select_multiple, and might fire bsmSelect. I'm not sure what the problem here is exactly, but that's the best I can come up with.
I think you want to set your HTML in the success of the Ajax call, something like:
function loadNewOptions(val) {
$.ajax({
type: 'GET',
url: /*My URL*/,
success: function(data) {
$('#my_select_multiple').html(data).bsmSelect();
}
});
}
And then calling like:
$('#my_select_simple').change() {
loadNewOptions($(this).val());
}
$(document).ready(function() {
$('#my_select_simple').change() {
$('#my_select_multiple').load("your Url", function(){
$('#my_select_multiple').bsmSelect();
});
}
});
something like this should work.
.load will put whatever your url returns into #my_select_multiple
the first parameter is the url to load, and the 2nd is a function to call when it is done. which is where you need to set up your fancy selector.
Ok, I opened a ticket and bsmSelect developer has answered me in minutes. Great!
To let bsmSelect know about its select changes, you have to trigger a change event on the select. There is no need to call bsmSelect again.
So it can be that way:
function loadNewOptions(val) {
var r = $.ajax({
type: 'GET',
url: /*My URL*/,
success: function(data) {
$('#my_select_multiple').html(data).trigger('change');
}
}).responseText;
return r;
}
$('#my_select_simple').change(function() {
loadNewOptions($(this).val());
});

Categories