execute ajax inside condition before execute next ajax - javascript

I have two tables in a database , when pressing the submit button I want to insert new trader into trader table and get id using laravel 5.2 by using post ajax under condition ,then execute another post ajax for invoice insert , but the problem in this case is when I press the submit it execute second ajax before the first ajax .. why?
$(document).ready(function(e) {
$('#invoiceForm').validate({
//rules: itemRules,
errorPlacement: function (element) {
return false;
},
submitHandler: function (event) {
//event.preventDefault();
// $('#selectedTraderName').valid();
var allItems = [];
$('tr.inputsItem').each(function () {
rowData = $(this).children('td').find('.form-control').map(function () {
return $(this).val();
}).get();
rowData.push(parseInt($(this).children('td').find('strong#autoTotal').text().trim()));
if($('select[id=selectedTraderName]').val() <= lastTraderID) {
rowData.push($('select[id=selectedTraderName]').val());
}
else{
newTrader = [];
newTrader.push($('#name').val());
newTrader.push($('#traderMail').val());
newTrader.push($('#mobileNumber').val());
newTrader.push($('#address').val());
$.ajax({
type: 'POST',
url: insertNewTrader,
data:{_token:token, trader:newTrader}
}).done(function (msg) {
rowData.push(msg['id']);
});
}
alert(rowData[6]);
allItems.push(rowData);
$.ajax({
type: 'POST',
url: insertNewItem,
data:{_token:token, items:allItems}
}).done(function () {
alert('done');
});
});
}
});

Of course, you can't nest ajax calls because of the if/else statement instead you can use a Deferred object like this:
rowData.push(parseInt($(this).children('td').find('strong#autoTotal').text().trim()));
// Create a new Deferred object
var deferred = $.Deferred();
if ($('select[id=selectedTraderName]').val() <= lastTraderID) {
rowData.push($('select[id=selectedTraderName]').val());
//Nothing to wait just resolve the deferred
deferred.resolve();
} else {
newTrader = [];
newTrader.push($('#name').val());
newTrader.push($('#traderMail').val());
newTrader.push($('#mobileNumber').val());
newTrader.push($('#address').val());
$.ajax({
type: 'POST',
url: insertNewTrader,
data: {
_token: token,
trader: newTrader
}
}).done(function(msg) {
rowData.push(msg['id']);
//Resolve the deferred
deferred.resolve();
});
}
//When the deferred resolved then execute your next ajax request
deferred.then(function() {
allItems.push(rowData);
$.ajax({
type: 'POST',
url: insertNewItem,
data: {
_token: token,
items: allItems
}
}).done(function() {
alert('done');
});
});
I hope thsi will help you.

Check the 2nd ajax request condition and call 2nd ajax function on 1st ajax function complete section/success section.
$.ajax({
type: 'POST',
url: insertNewItem,
data:{_token:token, items:allItems},
complete : function(){
//call ur 2nd ajax request here
},
success : function(data){
console.log(data);
//call ur 2nd ajax request here
}
});

Related

Reusing a JavaScript AJAX call before another AJAX call

I have two buttons that both performs AJAX call:
$("#save").click(function() {
$.ajax({
type: "POST",
url: saveEntryURL,
data: { id: $("#id").val() },
success: function(r) {
...
},
error: function(r) {
...
}
})
})
$("#tag-as-final").click(function() {
$.ajax({
type: "POST",
url: finalizeEntryURL,
data: { id: $("#id").val() },
success: function(r) {
...
},
error: function(r) {
...
}
})
})
The requirement is that when the user click the finalize button, the system will first perform a save before actually tagging it as final. To reuse the code attached to the save button, I call the onclick listener of the save button before the actual AJAX call like this:
$("#tag-as-final").click(function() {
$("#save").click()
^^^^^^^^^^^^^^^^^^
$.ajax({
type: "POST",
url: finalizeEntryURL,
But it will not do "save-and-finalize-after" behavior since both AJAX calls are asynchronous. I need to run one after another, but cannot afford to make the AJAX call of the save button synchronous (I'm doing also a lot of other things while the tagging occurs occurs). I know this would be silly but I'm thinking something similar to...
$("#tag-as-final").click(function() {
$("#save").click().peformAsyc()
^^^^^^^^^^^^
$.ajax({
type: "POST",
url: finalizeEntryURL,
...that will force it to finish performing first the chained function before continuing, but I know that is not available. Is there any way to do this? My current work-around is placing the same save AJAX function inside the finalize AJAX function, though it doesn't allow me to code DRY (Don't Repeat Yourself):
$("#tag-as-final").click(function() {
$.ajax({
type: "POST",
url: saveEntryURL,
data: { id: $("#id").val() },
success: function(r) {
...
$.ajax({
type: "POST",
url: finalizeEntryURL,
data: { id: $("#id").val() },
success: function(r) {
...
},
error: function(r) {
...
}
})
},
error: function(r) {
...
}
})
})
It's pretty simple, you are better using jquery "promises". Like so:
var generalSettings = { }; //Settings for AJAX call.
var jqXHR = $.ajax(generalSettings); //Do AJAX call.
generalSettings.data = 'newdata'; //update generalSettings
jqXHR.done(function(data){
$.ajax(generalSettings); //New Petition with updated settings.
});
This is using ES6 promises and jQuery promises:
function doAjaxAsPromise(settings){
return new Promise(function(resolve){
var jqXHR = $.ajax(settings);
jqXHR.done(function(data){
resolve(data);
});
});
}
var settings = { };
var petition = doAjaxAsPromise(settings);
var secondpetition = petition.then(function(data){
//work with data
//new settings
var settings = { };
return doAjaxAsPromise(settings);
});
var thirdpetition = secondpetition.then(function(data){
//work with data
//new settings
var settings = { };
return doAjaxAsPromise(settings);
});
//If needed to reuse settings object outside promise scope:
//var settings = Object.create(settings);
Some other nice thing you can do for code reuse:
function save(settings) {
var prom = doAjaxAsPromise(settings);
return prom.then(function(data){
//do something with your data.
});
}
function tagAsFinal(savedPromise, settings){
return savedPromised.then(function(){
var prom = doAjaxAsPromise(settings);
return prom.then(function(data){
//work with data;
});
});
}
$('save').on('click', function(){
save(settings); //settings = $.ajax settings.
});
$('tagAsFinal').on('click', function(){
var generalSettings = { };
var settingsone = Object.create(generalSettings);
var settingstwo = Object.create(generalSettings);
var saved = save(settingsone); //$.ajax settings.
tagAsFinal(saved, settingstwo);
});
//Can still be reduced.

Why Html dialog opening data from cache

I have dilaog box which loads data in success function of an ajax call as follows.
$.ajax({
url: '#Url.Action("GetPolicyPremiumAllocation", "Policy")',
data: { policyID: selPolicyId },
type: 'POST',
success: function (data) {
if (data.length > 0) {
alert(data);
document.getElementById("modal_dialog").innerHTML = "";
// $("#modal_dialog").empty();
$("#modal_dialog").load(data,function( ) {
$("#close-button-id").on("click", CloseDialog);
});
$("#modal_dialog").dialog("open");
}
}
});
First time the div of dilaog is loading correct data.But Second time,it just shows the old data. I have tried to clear cache in the index action of my controller.Unable to figure out how to solve this.Please help.
Set ajax cache option to false:
$.ajax({
url: '#Url.Action("GetPolicyPremiumAllocation", "Policy")',
data: { policyID: selPolicyId },
cache:false,
type: 'POST',
success: function (data) {
if (data.length > 0) {
alert(data);
document.getElementById("modal_dialog").innerHTML = "";
// $("#modal_dialog").empty();
$("#modal_dialog").load(data,function( ) {
$("#close-button-id").on("click", CloseDialog);
});
$("#modal_dialog").dialog("open");
}
}
});
Or decorate your Action with [OutputCache(NoStore = true, Duration = 0)]

Passing post variables through ajax

I have a link:
<a class="tag" wi_id="3042" wl_id="3693" for_user_id="441" href="#a">
which triggers an ajax call
$(".tag").click(function() {
var for_user_id = $(this).attr("for_user_id");
var wl_id = $(this).attr("wl_id");
var wi_id = $(this).attr("wi_id");
$.ajax({
type: "POST",
url: "/ajax/actions/tag.php",
data: {
'for_user_id': 'for_user_id',
'wl_id': 'wl_id',
'wi_id': 'wi_id'
},
success: function(data){
$(this).text("You've tagged this");
$(this).closest('.gl_buttons_holder').toggleClass('gl_buttons_holder gl_buttons_holder_tagged');
$(this).closest('.gl_buttons').addClass('tagged');
}
});
return false;
});
But in the console I see the following:
TypeError: e is undefined
The ajax file gets processed but the POST data is blank, and the success actions do not happen, so it gets posted with zeros and classes are not changed
I have stared and stared... anything obvious?
this is not passed automatically to the AJAX callback function. You can use the context: parameter to tell jQuery to pass it:
$.ajax({
type: "POST",
url: "/ajax/actions/tag.php",
data: {
'for_user_id': for_user_id,
'wl_id': wl_id,
'wi_id': wi_id
},
context: this,
success: function(data){
$(this).text("You've tagged this");
$(this).closest('.gl_buttons_holder').toggleClass('gl_buttons_holder gl_buttons_holder_tagged');
$(this).closest('.gl_buttons').addClass('tagged');
}
});
You're sending your data wrong, don't call your variables inside single quotes.
$(".tag").click(function() {
var for_user_id = $(this).attr("for_user_id");
var wl_id = $(this).attr("wl_id");
var wi_id = $(this).attr("wi_id");
$.ajax({
type: "POST",
url: "/ajax/actions/tag.php",
data: {
'for_user_id': for_user_id,
'wl_id': wl_id,
'wi_id': wi_id
},
success: function(data){
$(this).text("You've tagged this");
$(this).closest('.gl_buttons_holder').toggleClass('gl_buttons_holder gl_buttons_holder_tagged');
$(this).closest('.gl_buttons').addClass('tagged');
}
});
return false;
});

Ajax, prevent multiple request on click

I'm trying to prevent multiple requests when user click on login or register button. This is my code, but it doesn't work. Just the first time works fine, then return false..
$('#do-login').click(function(e) {
e.preventDefault();
if ( $(this).data('requestRunning') ) {
return;
}
$(this).data('requestRunning', true);
$.ajax({
type: "POST",
url: "/php/auth/login.php",
data: $("#login-form").serialize(),
success: function(msg) {
//stuffs
},
complete: function() {
$(this).data('requestRunning', false);
}
});
});
Any ideas? Thanks!
The problem is here:
complete: function() {
$(this).data('requestRunning', false);
}
this no longer points to the button.
$('#do-login').click(function(e) {
var me = $(this);
e.preventDefault();
if ( me.data('requestRunning') ) {
return;
}
me.data('requestRunning', true);
$.ajax({
type: "POST",
url: "/php/auth/login.php",
data: $("#login-form").serialize(),
success: function(msg) {
//stuffs
},
complete: function() {
me.data('requestRunning', false);
}
});
});
Use on() and off(), that's what they are there for :
$('#do-login').on('click', login);
function login(e) {
e.preventDefault();
var that = $(this);
that.off('click'); // remove handler
$.ajax({
type: "POST",
url: "/php/auth/login.php",
data: $("#login-form").serialize()
}).done(function(msg) {
// do stuff
}).always(function() {
that.on('click', login); // add handler back after ajax
});
});
In your ajax callbacks the context (this) changes from the outer function, you can set it to be the same by using the context property in $.ajax
$.ajax({
type: "POST",
url: "/php/auth/login.php",
data: $("#login-form").serialize(),
context: this, //<-----
success: function(msg) {
//stuffs
},
complete: function() {
$(this).data('requestRunning', false);
}
});
You can disable the button.
$(this).prop('disabled', true);
I have also faced a similar problem.
Just adding $('#do-login').attr("disabled", true); gives me the solution.
$('#do-login').click(function(e) {
e.preventDefault();
$('#do-login').attr("disabled", true);
.........
.........
Here do-login is button id.
I've tried this and worked very fine for me, I was having trouble that $.ajax send more request until results return,
var settings = {
"url": "/php/auth/login.php",
"method": "POST",
"timeout": 0,
"async": false,
"headers": {
"Content-Type": "application/json; charset=utf-8"
},
"data": jsondata, //data pass here is in JSON format
};
$.ajax(settings).done(function (ress) {
try{
console.log(ress, "Result from Ajax here");
}
catch(error){
alert(error);
console.log(ress);
}
});
async : false worked for me.
Thanks.
Or you can do it by $(this).addClass("disabled"); to you button or link and after click is performed, you can $(this).removeClass("disabled");.
// CSS
.disabled{
cursor: not-allowed;
}
// JQUERY
$('#do-login').click(function(e) {
e.preventDefault();
$(this).addClass("disabled");
$.ajax({
type: "POST",
url: "/php/auth/login.php",
data: $("#login-form").serialize(),
context: this,
success: function(msg) {
//do more here
$(this).removeClass("disabled");
},
});
});
P.S. If you use bootstrap css, you do not need the css part.
I found the approach useful. I've implemented it as a general purpose function for jQuery with ES6.
export default function (button, promise) {
const $button = $(button);
const semaphore = 'requestRunning';
if ($button.data(semaphore)) return null;
$button.data(semaphore, true);
return promise().always(() => {
$button.data(semaphore, false);
});
}
Because $.ajax() returns a promise, you simply pass in the promise and the function takes care of the rest.
Roughly speaking, here's the usage.
import preventDoubleClick from './preventdoubleclick';
...
button.click(() => {
preventDoubleClick(this, () => $.ajax()
.done(() => { console.log("success") }));
});
This function can help you with control multi Ajax requests and it's has timeout function which can return flag status to 0 after ex. 10sec (In case the server took more than 10 seconds to respond)
var Request_Controller = function(Request_Name = '', Reactivate_Timeout = 10000)
{
var a = this;
a.Start_Request = function(){
if(window.Requests == undefined){
window.Requests = {};
}
window.Requests[Request_Name] = {'Status' : 1, 'Time': + new Date()};
}
a.End_Request = function(){
if(window.Requests == undefined){
window.Requests = [];
}
window.Requests[Request_Name] = undefined;
}
a.Is_Request_Running = function(){
if(window.Requests == undefined || window.Requests[Request_Name] == undefined){
return 0;
}else{
var Time = + new Date();
// Reactivate the request flag if server take more than 10 sec to respond
if(window.Requests[Request_Name]['Time'] < (Time - Reactivate_Timeout))
{
return 0;
}else{
return 1
}
}
}
}
To use it:
var Request_Flag = new Request_Controller('Your_Request_Name');
if(!Request_Flag.Is_Request_Running()){
Request_Flag.Start_Request();
$.ajax({
type: "POST",
url: "/php/auth/login.php",
data: $("#login-form").serialize(),
success: function(msg) {
//stuffs
},
complete: function() {
Request_Flag.End_Request();
}
});
}
for prevent multiple ajax request in whole site. For example: If use ajax request in other ajax page, Using ajax in php loop, etc, Give you multiple ajax request with one result. I have solution:
Use window.onload = function() { ... }
instead of
$(document).ready(function(){ ... });
on the main index.php page. Its will be prevent all multi request. :)

How to nest jQuery .when calls with callbacks?

I have a function that loads a section.
function loadSection(sectionId, onLoaded) {
$.when(
loadTemplate(sectionId),
// etc
)
.then(function () {
// removed for brevity
}
}
In the loadTemplate function I fade out the current template, and after the fadeout I load the new template.
function loadTemplate(sectionId) {
// Fade out current template.
return $content.fadeOut(function () {
// After fade out, load new template via ajax.
$.ajax({
url: settings.apiUrl + 'GetSectionTemplate',
data: { sectionId: sectionId },
type: 'post',
success: function (template) {
// Add new content and fade in new template.
$content
.html(template)
.fadeIn();
}
});
});
}
The problem is that the $.when only waits for the fadeOut function to finish before moving on. I need it to wait for both the fadeOut and the ajax call to finish, but I need the ajax call to execute only after the fadeOut finishes.
Create a deferred object, return it, and then resolve it when the ajax completes:
function loadTemplate(sectionId) {
var deferred = $.Deferred();
$content.fadeOut(function () {
$.ajax({
url: settings.apiUrl + 'GetSectionTemplate',
data: { sectionId: sectionId },
type: 'post',
success: function (template) {
$content.html(template).fadeIn();
deferred.resolve();
}
});
});
return deferred;
}
Just use an Array to push the Promise objects into and return that. Like
function loadTemplate(sectionId) {
var promises = [ ];
// Fade out current template.
promises.push($content.fadeOut());
promises.push($.ajax({
url: settings.apiUrl + 'GetSectionTemplate',
data: { sectionId: sectionId },
type: 'post',
success: function (template) {
// Add new content and fade in new template.
$content
.html(template)
.fadeIn();
}
}));
return promises;
}
and then call it like
$.when.apply( null,
loadTemplate(sectionId)
).then(function() {
});
If you need more control over the order of promise-objects resolve or you want to intercept / filter results, you can also use .pipe() to somewhat concat the promises.
Try making your ajax call synchronous:
$.ajax({
async: false,
url: settings.apiUrl + 'GetSectionTemplate',
...
...

Categories