So this is my function, it deletes people from a list if you click on certain part of the form:
function ParticipantsDeleteClick(model, url) {
for (i in model.Participants) {
$("#delete" + i).click(function () {
$.ajax({
url: url,
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({ id: model.Participants[i].Id }),
success: function (result) {
result ? $("#participant" + i).remove() : alert("Delete failed");
},
error: function () {
alert("Could not get a response from the server.");
}
});
});
}
}
For some reason, it doesn't matter which person you click on, it will always delete the last person from the list. And it only works once because once the last "i" gets deleted, every other click function points to that dom element with the last i's value.
I don't know why every time I'm adding a click function it all points to the last i's value in the loop. I modified the function adding a temp variable that took i's integer value and that didn't work either:
function ParticipantsDeleteClick(model, url) {
for (i in model.Participants) {
var temp = parseInt(i);
$("#delete" + temp).click(function () {
$.ajax({
url: url,
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({ id: model.Participants[temp].Id }),
success: function (result) {
result ? $("#participant" + temp).remove() : alert("Delete failed");
},
error: function () {
alert("Could not get a response from the server.");
}
});
});
}
}
So I'm not sure how I can get this to work.
i is always overwritten in the loop. You need a closure, eg by using $.each(function(){..}, or by wrapping the loop's body in a self-invoking function.
function ParticipantsDeleteClick(model, url) {
$.each(model.Participants, function(i){ //The `function` creates a closure
$("#delete" + i).click(function () {
$.ajax({
url: url,
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({ id: model.Participants[i].Id }),
success: function (result) {
result ? $("#participant" + i).remove() : alert("Delete failed");
},
error: function () {
alert("Could not get a response from the server.");
}
});
});
}
}
Basically, you need to introduce a closure to capture the value of i each time around the loop. Using $.each() will introduce a closure for you (something like this)
function ParticipantsDeleteClick(model, url) {
$.each(model.Participants, function(i,v) {
$("#delete" + i).click(function () {
$.ajax({
url: url,
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({ id: model.Participants[i].Id }),
success: function (result) {
result ? $("#participant" + i).remove() : alert("Delete failed");
},
error: function () {
alert("Could not get a response from the server.");
}
});
});
});
}
You have 3 scope levels here:
loop scope
click handler scope
ajax success handler scope
So you will need for each of those scope preserve and pass the variables. The .bind() method allows you to pass arguments to the callback from the outer scope and the context parameter allows you to pass parameters to the AJAX success callback. So:
$.each(model.Participants, function(index, participant) {
var data = { index: index, participant: participant };
$('#delete' + index).bind('click', data, function(evt) {
// at this stage evt.data will point to what the data variable was pointing
// from the outer scope but at the moment this handler was bound
$.ajax({
url: url,
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({ id: evt.data.participant }),
context: evt.data.index,
success: function (result) {
// since we have used the context parameter at this stage
// this will point to this parameter which is simply the index
result ? $('#participant' + this).remove() : alert('Delete failed');
},
error: function () {
alert('Could not get a response from the server.');
}
});
});
});
Or to break this into separate functions to make it more clear:
function handleClick(evt) {
$.ajax({
url: url,
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({ id: evt.data.participant }),
context: evt.data.index,
success: ajaxSuccess,
error: ajaxError
});
}
function ajaxSuccess(result) {
result ? $('#participant' + this).remove() : alert('Delete failed');
}
function ajaxError() {
alert('Could not get a response from the server.');
}
and then finally:
function ParticipantsDeleteClick(model, url) {
$.each(model.Participants, function(index, participant) {
var data = { index: index, participant: participant };
$('#delete' + index).bind('click', data, handleClick);
});
}
Related
I have a view that takes a list of a model as the Model, so
#model List<Collections.Models.Status>
I want to pass this list as the data for an Ajax call, but I keep getting "System.Collections.Generic.List[Collections.Models.Status]" instead of the values in the model.
Here's the Ajax code:
$.ajax({
url: "/Home/Update",
data: JSON.stringify(#Model),
type: 'POST',
dataType: 'json',
success: function (responseJSON) {
if (responseJSON.message == 'success') {
alert('here');
}
},
error: function (error) {
showModal("Error: " + error.message);
}
});
Which translates in the debugger to:
$.ajax({
url: "/Home/Update",
data: JSON.stringify(System.Collections.Generic.List`1[Collections.Models.CollectionStatus]),
type: 'POST',
dataType: 'json',
success: function (responseJSON) {
if (responseJSON.message == 'success') {
alert('here');
}
},
error: function (error) {
showModal("Error: " + error.message);
}
});
How do I pass the actual values of the list instead of System.Collections.Generic.List[Collections.Models.Status]?
I've tried #Model.ToList(), #Html.Raw(Model), neither worked.
set contentType property to application/json.
and use below code to set data property
data: JSON.stringify({'your controllers parameter name': '#Model'})
My second ajax call always returning undefined.
var getrpmData = fetchAjaxData(
{
"MachineID": MachineID,
"diaVal": diaVal,
"ggVal": ggVal,
"ITEMID": ITEMID
},
"url_to_call");
getrpmData.then((rpmData) => {
console.log(rpmData.d);//getting desired value from this
if (rpmData.d) {
shifHourUsigRPM(rpmData.d);
}
})
.then((prodRate) => {
console.log(prodRate.d.KnittingQty);//not getting value
})
.fail((err) => {
console.log(err);
}
);
// Generic function to make an AJAX call
var fetchAjaxData = function (dataParam, dataURL) {
// Return the $.ajax promise
return $.ajax({
beforeSend: function () { $.blockUI(); },
complete: function () { $.unblockUI(); },
type: "POST",
url: dataURL,
dataType: "JSON",
contentType: "application/json;charset=utf-8",
data: JSON.stringify(dataParam)
});
}
function shifHourUsigRPM(rpm) {
var KnittingWorkOrderId = GetValue($("#cmbKWO").val(), 'dlKWO');
var ITEMID = $("#cmbFabName").val();
var machineId = GetValue($("#cmbMachineID").val(), 'dlMachineID');
//fetchAjaxData(
// { "this_RPM": rpm, "fab": ITEMID, "machineId": machineId, "KWOID": KnittingWorkOrderId },
// "pageKnittingProductionPlanning_MachineWise.aspx/KPP_Load_QtyByRPM");
return $.ajax({
type: "POST",
beforeSend: function () { $.blockUI(); },
complete: function () { $.unblockUI(); },
url: "pageKnittingProductionPlanning_MachineWise.aspx/KPP_Load_QtyByRPM",
dataType: "JSON",
contentType: "application/json;charset=utf-8",
data: JSON.stringify({ "this_RPM": rpm, "fab": ITEMID, "machineId": machineId, "KWOID": KnittingWorkOrderId }),
success: function (data) {
//var result = data.d;
}
});
my back end web service is working fine, and returning desired value but not getting that value on second console.log call
getting below response from network response:
{"d":{"__type":"BLL.Kniting_BLL.KnittingQty","TotalFabNeed":"5 is production rate","RemFabQty":null}}
I'm expecting my second console.log should print
"5 is production rate"
, but getting undefined printed on console
Your first then callback is not returning a value, so the second then callback
will get undefined as argument.
You should return the value that shifHourUsigRPM(rpmData.d) returns (i.e. a promise), so add return before that call.
getrpmData.then((rpmData) => {
if (rpmData.d) {
return shifHourUsigRPM(rpmData.d);
// ^^^^^^
}
})
I have created a save(id) function that will submit ajax post request. When calling a save(id). How to get value/data from save(id) before going to next step. How to solve this?
For example:
function save(id) {
$.ajax({
type: "POST",
url: "/post/",
dataType: "json",
contentType: 'application/json',
data: JSON.stringify({
id: id,
}),
success: function (data) {
return data;
},
error: function (error) {
return data;
}
});
}
Usage:
$('.btn-create').click(function () {
var id = 123;
data = saveArea(id); //get data from ajax request or error data?
if (data) {
window.location = "/post/" + data.something
}
}
You have two options, either run the AJAX call synchronously (not recommended). Or asynchronously using callbacks
Synchronous
As #Drew_Kennedy mentions, this will freeze the page until it's finished, degrading the user experience.
function save(id) {
return $.ajax({
type: "POST",
url: "/post/",
dataType: "json",
contentType: 'application/json',
async: false,
data: JSON.stringify({
id: id,
})
}).responseText;
}
$('.btn-create').click(function () {
var id = 123;
// now this will work
data = save(id);
if (data) {
window.location = "/post/" + data.something
}
}
Asynchronous (recommended)
This will run in the background, and allow for normal user interaction on the page.
function save(id, cb, err) {
$.ajax({
type: "POST",
url: "/post/",
dataType: "json",
contentType: 'application/json',
data: JSON.stringify({
id: id,
}),
success: function (data) {
cb(data);
},
error: err // you can do the same for success/cb: "success: cb"
});
}
$('.btn-create').click(function () {
var id = 123;
save(id,
// what to do on success
function(data) {
// data is available here in the callback
if (data) {
window.location = "/post/" + data.something
}
},
// what to do on failure
function(data) {
alert(data);
}
});
}
Just make things a bit simpler.
For starters just add window.location = "/post/" + data.something to the success callback.
Like this:
function save(id) {
return $.ajax({
type: "POST",
url: "/post/",
dataType: "json",
contentType: 'application/json',
data: JSON.stringify({
id: id,
}),
success:function(data){
window.location = "/post/" + data.something
}
}).responseText;
}
Or by adding all your Ajax code within the click event.
$('.btn-create').click(function () {
var id = "123";
$.ajax({
type: "POST",
url: "/post/",
dataType: "json",
contentType: 'application/json',
data: JSON.stringify({
id: id,
}),
success: function (data) {
window.location = "/post/" + data.something
},
error: function (error) {
console.log(error)
}
});
}
I have three functions that called as shown below (Functions not included):
Code:
$("#btnSubmit").click(function() {
var data = JSON.stringify(getAllSourcepData());
console.log(data);
$.ajax({
url: 'closures.aspx/SaveSourceData',
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({
'empdata': data
}),
success: function() {
alert("Data Added Successfully");
},
error: function() {
alert("Error while inserting data");
}
});
});
$("#btnSubmit").click(function() {
var data = JSON.stringify(getAllSpouseData());
console.log(data);
$.ajax({
url: 'closures.aspx/SaveSpousData',
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({
'empdata': data
}),
success: function() {
alert("Data Added Successfully");
},
error: function() {
alert("Error while inserting data");
}
});
});
$("#btnSubmit").click(function() {
var data = JSON.stringify(getAllDividentData());
console.log(data);
$.ajax({
url: 'closures.aspx/SaveDividentData',
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({
'empdata': data
}),
success: function() {
alert("Data Added Successfully");
},
error: function() {
alert("Error while inserting data");
}
});
});
When data is submitted successfully, three alert boxes popup, each with same message: "Data Added Successfully".
This forces user to have to close three popup boxes.
Is there a way to disable the success alert boxes leaving just one? Or even all three be disabled allowing me to come up with a custom Success message?
You could also simplified your code by using Promise.all:
$("#btnSubmit").click(function() {
var allSourcepData = JSON.stringify(getAllSourcepData());
var allSpouseData = JSON.stringify(getAllSpouseData());
var allDividentData = JSON.stringify(getAllDividentData());
Promise.all([
getData('closures.aspx/SaveSourceData', allSourcepData),
getData('closures.aspx/SaveSpousData', allSpouseData),
getData('closures.aspx/SaveDividentData', allDividentData)
])
.then( alert )
.catch( alert )
});
function getData(url, data)
{
return new Promise((resolve, reject){
$.ajax({
url: url,
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({
'empdata': data
}),
success: () => { resolve("Data Added Successfully") },
error: () => { reject("Error while inserting data"); }
});
})
}
You need to wait until all ajax requests are complete, like in this answer
So in your case you need to create functions for all $.ajax calls like this:
function ajax1() {
var data = JSON.stringify(getAllSourcepData());
$.ajax({
url: 'closures.aspx/SaveSourceData',
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({
'empdata': data
}),
success: function() {
alert("Data Added Successfully");
},
error: function() {
alert("Error while inserting data");
}
});
}
// add ajax2() and ajax3() ...
And then use only one click handler like this:
$("#btnSubmit").click(function() {
$.when(ajax1(), ajax2(), ajax3()).then(function(a1, a2, a3){
// success, display message
}, function(){
// exception
});
});
You can reorder a little your code to use the deferred method to jQuery 1.5+ otherwise you can implement as this answer:
jQuery callback for multiple ajax calls
Why you want to call 3 times for button click?
Why not put them all together?
Any how you can use variable as isAlertToBeShown= false and after pushing data make it has true. finally check the variable is true or false.
I need to make an api call for 100 rows to populate description (which I prefer to do it in parallel). However some of rows might not have description in this case api will return 404. I need to show a warning message when there are a row or rows without description and remove those rows from modal data which means I need a complete callback or done callback. However the completeCallback is not being called and I "think" it's because some of rows doesn't have description.
Could you please tell me how to achieve that?
Here is my code:
function getDescription(processedData) {
$.ajax({
url: baseApiUrl + '/Summary?id=' + processedData.id,
type: 'GET',
dataType: 'json',
contentType: 'application/json',
success: function (data) {
processedData.SummaryDescription = data;
},
error: function (xhr, status, e) {
if(xhr.statusCode === 404){
processedData.SummaryDescription = '';
}else{
}
}
});
};
//Below line is in a look
parallelCallArray.push(getDescription.bind(null, processedData));
//Below line is out of loop
Async.parallel(parallelCallArray, function(err, result){
console.log('all calls completed...');
});
You're missing the callback parameter of your function(s) that are being executed in parallel. If you don't execute the callback, async will assume your functions haven't finished yet. Try something like this:
function getDescription(processedData, cb) {
$.ajax({
url: baseApiUrl + '/Summary?id=' + processedData.id,
type: 'GET',
dataType: 'json',
contentType: 'application/json',
success: function (data) {
processedData.SummaryDescription = data;
cb();
},
error: function (xhr, status, e) {
if (xhr.statusCode === 404) {
processedData.SummaryDescription = '';
} else {
}
cb(new Error(e));
}
});
}