JQuery event ahead of another

I have a form that actually consists of two forms. Each form is a reservation form. There are two drop-down lists in both forms - destination from and destination to . There is an even handler that calls AJAX to be able to destinations to when selecting / changing the destination.

Another event handler (round-trip check box) fills out the drop-down lists of the second form, switching recipients from the first form.

So, if the first form has:

 destination one: France destination two: Austria 

Then, if a round trip checked, the second form is immediately populated:

 destination one: Austria destination two: France 

The problem is that these two events do not interact correctly.

When this code is executed:

 id_form_1_destination_from.val(destination_to_0.val()); id_form_1_destination_to.val(destination_from_0.val()); id_form_1_destination_from.change(); id_form_1_destination_to.change(); 

The first line calls another handler that fills the second form (this is the only case when it is not needed). Since it is AJAX , the second line overtakes this AJAX , so now the second form is correctly filled out (assigned by the addressee from the first form), but when AJAX is done, it changes the choice of the destination two field.

Is there any way to avoid this? For example, to disable the event handler, or better, do JQuery until AJAX is complete and then continues. I cannot just do .off() in the destination to field, because I am using the select2 plugin.

Here is my JQuery :

 $(document).ready(function () { var destination_from_0 = $("#id_form-0-destination_from"); var destination_to_0 = $('#id_form-0-destination_to'); var ride_two = $('#ride_two'); $('.class-destination-from').on('change', function () { destination_from_changed.call(this); }); $("#id_round_trip").on('change', function () { if (($('#id_round_trip').is(':checked')) ) { var id_form_1_destination_from =$('#id_form-1-destination_from'); var id_form_1_destination_to = $('#id_form-1-destination_to'); ride_two.show('fast'); //id_form_1_destination_from.off(); id_form_1_destination_from.val(destination_to_0.val()).change(); //id_form_1_destination_from.on(); //id_form_1_destination_from.change(); id_form_1_destination_to.val(destination_from_0.val()).change(); }else{ ride_two.hide('fast'); ride_two.find(':input').not(':button, :submit, :reset, :checkbox, :radio').val('').change(); ride_two.find(':checkbox, :radio').prop('checked', false).change(); } }); $('.class-destination-to').on('change', destination_to_changed); }); function destination_to_changed() { var destination_id = $(this).val(); var arrival_container = $(this).siblings('.arrival-container'); var departure_container = $(this).siblings('.departure-container'); if (destination_id == '') { return; } $.ajax({ url: '/ajax/is-airport/' + destination_id + '/', success: function (data) { if (data.status == true) { arrival_container.hide("slow"); departure_container.show("slow"); } if (data.status == false) { departure_container.hide("slow"); arrival_container.show("slow"); } arrival_container.change(); departure_container.change(); } }) } function destination_from_changed() { var destination_id = $(this).val(); if (destination_id == '') { return; } var ajax_loading_image = $('#ajax-loading-image'); var destination_to = $(this).siblings('.class-destination-to'); destination_to.empty(); ajax_loading_image.show(); $.ajax({ url: '/ajax/get-destination-to-options/' + destination_id + '/', async:false, // ADDED NOW - THIS HELPED BUT IT NOT NECESSARY EVERYTIME success: function (data) { ajax_loading_image.hide(); destination_to.append('<option value="" selected="selected">' + "---------" + '</option>'); $.each(data, function (key, value) { destination_to.append('<option value="' + key + '">' + value + '</option>'); }); destination_to.change(); } }) } 
+5
source share
3 answers

If I understand correctly, you have a concurrency problem. Do you basically want your first ajax call to be interrupted before calling the second on the right?

I don't see any ajax request in your code, but I think the async: false parameter may be what you need.

Check the documentation: http://api.jquery.com/jquery.ajax/

Hope this helps

+2
source

You definitely have the classic "race condition" that happens here.

Since AJAX calls seem rather unrelated to each other, you may need to add code on the JavaScript side so that potentially racing situations cannot occur. For example, to find out that the combo is “populating” if you submitted an AJAX request to fill it out but have not yet received a response. You can disable certain buttons.

By the way, in such situations, when it comes to two (or more ...) forms, I like to try to centralize the logic. For example, there may be a “singleton object” whose task is to know the current status of everything that is done on the host or with it. The state machine (FSM) works very well here (mumble, mumble ...). This object can transmit events to inform "listeners" when they need to change their buttons, etc.

+1
source

You need to cancel the first AJAX request before you start the second. From this SO question:

Cancel Ajax requests with jQuery

 var xhr; function getData() { if (xhr) { xhr.abort(); } xhr = $.ajax(...); } 
0
source

All Articles