$.done() code gets executed before $.when() - javascript

In my project I m using 2 versions of JQuery.js, so I resolved the conflict using $.noConflict() for my latest version of JQuery to variable named jq172. Now I have used jq172.when().done()construct to show loading status image until all ajax request are processed completely. The code is as follows.
jq172.when(
DisplayPOXOrderStatistics(fromDate, toDate),
DisplayPOXCompletedOrdersData(fromDate, toDate),
DisplayPOXCompletedOrderPieChart(fromDate, toDate),
DisplayCurrentYearlyTrends())
.done(function (a1,a2,a3,a4)
{
$("#loading").hide();
});
where functions in the jq172.when() are coded as follows,
function DisplayPOXOrderStatistics(fromDate, toDate) {
return $.ajax({
type: "POST",
url: '#Url.Action("DisplayPOXOrderStatistics", "Home")',
dataType: "json",
data: { FromDate: fromDate, ToDate: toDate },
success: function (data) {application code.....}
});
}
function DisplayPOXCompletedOrdersData(fromDate, toDate) {
return $.ajax({
type: "POST",
url: '#Url.Action("DisplayPOXCompletedOrders", "Home")',
data: { FromDate: fromDate, ToDate: toDate },
dataType: "json",
success: function (data) { some code....}
});
}
& rest 2 functions are coded in the same way as above
Now my code in .done() to hide loading image dive should be executed after all 4 ajax call is finished, but currently it gets executed immediately after function call is dispatched. Can anybody figure out the problem in my code.
Thanks in Advance...
Here is the definition of rest 2 functions..
function DisplayPOXCompletedOrderPieChart(fromDate, toDate) {
return $.ajax({
type: "POST",
url: '#Url.Action("POXCompletedOrderPieChart", "Home")',
data: { FromDate: fromDate, ToDate: toDate },
dataType: "json",
success: function (data) {
$('#POXCompletedOrdersPie').empty();
var dataSet = [];
var isDataAvailable = false;
for (var i = 0; i < data.length ; i++) {
var newElement = { label: data[i].Name, data: parseFloat(data[i].ColumnValue), color: Color[i] };
dataSet.push(newElement);
if (newElement.data > 0)
isDataAvailable = true;
}
if (dataSet.length != 0 && isDataAvailable) {
$.plot($("#POXCompletedOrdersPie"), dataSet, {
series: {
pie: {
show: true
}
},
legend: {
show: false
}
});
}
else {
$("#POXCompletedOrdersPie").empty();
$("#POXCompletedOrdersPie").append("<html><p> <b>" + "#Html.Raw(VirtuOxAdvDME.Dashboard_PieChart_POXCompletedOrder_NoData)" + "</b> </p><html>");
}
}
});
}
function DisplayCurrentYearlyTrends() {
$("#DisplayCurrentYear").html($('#selectCurrentYear option:selected').text());
return $.ajax({
url: '#Url.Action("DisplayCurrentYearlyTrends", "Home")',
data: { selectedCurrentYear: $('#selectCurrentYear option:selected').text() },
type: 'POST',
dataType: 'json',
success: function (data) {
var DataValues = [], TickData = [];
var i = undefined;
$.each(data, function (index, item) {
i = (index + 1) * 2;
DataValues.push({ data: [i, item.Value], color: Color[i] });
DataValues.push([i, item.Value]);
TickData.push([i, item.MonthName]);
});
$.plot($("#CurrentYearlyTrendsBar"), [{ data: DataValues, color: "#3D69AA" }],
{
series: { bars: { show: true } },
bars: {
barWidth: 1.5,
align: "center"
},
xaxis: {
ticks: TickData,
axisLabelUseCanvas: true,
labelAngle: -90,
},
yaxis: { axisLabelUseCanvas: true },
grid: { hoverable: true }
});
$("#CurrentYearlyTrendsBar").UseTooltip();
}
});
}

Probably your $.ajax calls (from the old jQuery version) do not return jqXHR objects which implement the Promise interface, a feature that was introduced with v1.5. when would see the objects as plain values then and resolve immediately.
To fix this, use jq172.ajax() instead, or use a (single) up-to-date jQuery and update your legacy code.

this is from the jquery site
in the multiple-Deferreds case where one of the Deferreds is rejected, jQuery.when immediately fires the failCallbacks for its master Deferred. Note that some of the Deferreds may still be unresolved at that point. If you need to perform additional processing for this case, such as canceling any unfinished ajax requests, you can keep references to the underlying jqXHR objects in a closure and inspect/cancel them in the failCallback.
check your ajax calls and make sure no one is getting rejected. You can do this in the
developers console->network tab
generally becomes accessible after pressing F12.

Related

How to properly code Javascript / Ajax for use with Chart.js

I have a controller action in my MVC project that creates a json record with the components needed. This is working. The issue I am having is bringing it into a chart.js canvas. This will be a pie chart that shows all the related countries with a count of each. Json has this info. Originally this was setup to use google visualization but I want to use chart.js. I just started using it. Creating charts with static data is no issue but I am pulling the info from a SQL table and creating a json to read from.
I have tried using the same structure and calling the data: data[] but it doesn't work I have also tried data: getData, which is a var for the ajax function. I am getting the data per the council on refresh.
Here is my controller Action
public ActionResult CustomersByCountry()
{
CustomerEntities _context = new CustomerEntities();
var customerByCountry = (from c in _context.Addresses
group c by c.Country into g
orderby g.Count() descending
select new
{
Country = g.Key,
CountCustomer = g.Count()
}).ToList();
return Json(new { result = customerByCountry }, JsonRequestBehavior.AllowGet);
}
And here is the JavaScript/ajax - which is nested in a document.ready function with the rest of the charts.
EDIT - changed Ajax - Still not working
OrdersByCountry()
function OrdersByCountry() {
$.ajax({
url: '/admin/CustomersByCountry',
method: "GET",
dataType: "json",
error: function (_, err) {
console.log(_, err)
},
success: function (data) {
console.log (data);
var customer = $("#customerByCountryPieChart").get(0).getContext("2d");
console.log(customer)
var cpieChart = new Chart(customer, {
type: 'pie',
data: data,
options: {
responsive: true,
title: {
display: true,
text: "Customers By Country",
}
}
});
}
});
};
Edit - The now working code is below.
I changed it to get states instead of country, just to clear up possible confusion. It made more sense to me to get States rather than Country at this point. This is working - meaning displaying the graph, I still need to work on the labels etc.
OrdersByStates()
function OrdersByStates() {
$.ajax({
url: '#Url.Action("CustomersByStates", "Admin")',
data: JSON,
contentType: "application/json; charset=utf-8",
method: "get",
dataType: "json",
error: function (_, err) {
console.log(_, err)
},
success: function (response) {
console.log(response);
var jsonresult = response
var labels = jsonresult.result.map(function (e) {
return e.State;
});
var data = jsonresult.result.map(function (e) {
return e.CountCustomer;
});;
var ctx = document.getElementById("CustomerByStatePieChart").getContext("2d");
var cpieChart = new Chart(ctx, {
type: 'pie',
data:
{
datasets: [
{
backgroundColor: ["#46BFBD", "#F7464A"],
hoverBackgroundColor: ["#5AD3D1", "#FF5A5E"],
label: "Orders",
data: data,
}]
},
options: {
responsive: true,
title: {
display: true,
text: "Customers By Country",
}
}
});
}
});
};
});
try:
var cpieChart = new Chart(customer, {
type: 'pie',
data: data.result,
options: {
responsive: true,
title: {
display: true,
text: "Customers By Country",
}
}
});
the response from the server "data" var on your request is {result: LIST}

Appropriate js kendo template for website

I use only kendo template in my website and use this js:
kendo.cdn.telerik.com/2015.2.805/js/kendo.all.min.js
but this file very very large size (2.102 KB). I want Appropriate kendo js file for this sulotion but I dont know:
my codes is:
<script>
function FillSpecificationAttr(attrId) {
var template = kendo.template($("#template").html());
var ID = attrId;
var dataSource = new kendo.data.DataSource({
type: "json",
transport: {
read: {
url: "../AjaxFunctionPages.asmx/ProductSpecAttrList",
type: "POST",
contentType: "application/json; charset=utf-8",
data: {
ID: ID
}
},
destroy: {
url: "../../AjaxFunctionsAdminPages.asmx/TierPriceDelete",
type: "POST",
contentType: "application/json; charset=utf-8",
data: {
ID: ID
}
},
parameterMap: function (data, operation) {
if (operation != "read") {
// web service method parameters need to be send as JSON. The Create, Update and Destroy methods have a "products" parameter.
return JSON.stringify({ ID: data.Id })
}
else if (operation == "destroy") {
}
else {
// web services need default values for every parameter
data = $.extend({ sort: null, filter: null }, data);
return JSON.stringify(data);
}
}
},
schema: {
data: "d.Data"
},
requestStart: function () {
kendo.ui.progress($("#tblConfigProduct"), true);
},
requestEnd: function () {
kendo.ui.progress($("#tblConfigProduct"), false);
},
change: function () {
$("#tblConfigProduct").html(kendo.render(template, this.view()));
}
});
dataSource.read();
};
</script>
I think the template is defined in kendo.core.min.js file which in version 2017.2.504 is only 54KB of size. You will still need jQuery library as a required dependency added in your document.
Demo

Bootstrap-table : multiple tables , one function

I am on an custom ajax implementation for bootstrap-table (the documentation : http://bootstrap-table.wenzhixin.net.cn/documentation/) :
For some reason, I would like to have multiple bootstrap Tables (let's call them searchTable1 , searchTable2,etc). Each of these table will be set on a custom date range (30 last days, 60 last days,etc).
I would like to pass a parameter (like the table Jquery selector or any data-myCustomDataAttribute parameter) . How can I do that ? (I tried using call but bootstrap already call it on the ajaxCallback function so It seems I cannot use it here).
It will look like stupid to make x functions that are exactly the same except for two fields depending on the table. Does someone has an idea to do that ?
Here is my code :
$('#searchTable').bootstrapTable({
columns: [{
field: 'product',
title: 'Produit'
} , {
field: 'language',
title: 'Langue'
}, {
field: 'comment',
title: 'Commentaire'
}],
showRefresh: true,
ajax: provideFeedbacksList,
cache: false,
dataField: 'feedbacks',
totalField: 'total_size',
search: false,
sidePagination: 'server',
pagination: true
});
The ajax provider :
// I only used this example : http://issues.wenzhixin.net.cn/bootstrap-table/index.html#options/custom-ajax.html
function provideFeedbacksList(params) {
let tableData = params.data;
let serverCall = {};
// add limits and offset provided by bootstrap table
serverCall["page_offset"] = tableData.offset;
serverCall["page_size"] = tableData.limit;
// retrieve the date range for this table :
// will be easy If something like this was possible : params.jquerySelector.attr("date-range-start")
// will be easy If something like this was possible : params.jquerySelector.attr("date-range-end")
let json = JSON.stringify(serverCall);
$.ajax({
url: baseUri + "/feedbacks",
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
data: json,
success: function (reponse) {
params.success(reponse);
},
error: function (er) {
params.error(er);
}
});
}
Bonus, the call stack :
Finally found my answer , I have to wrapper it as a function to enable bootstrap table to pass also its data:
Self solved my issue :
js:
function callbacker(test){
console.log(test);
return function (params) {
console.log(params);
console.log(test);
let tableData = params.data;
let serverCall = {};
// add limits and offset provided by bootstrap table
serverCall["page_offset"] = tableData.offset;
serverCall["page_size"] = tableData.limit;
let json = JSON.stringify(serverCall);
$.ajax({
url: baseUri + "/feedbacks",
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
data: json,
success: function (reponse) {
params.success(reponse);
},
error: function (er) {
params.error(er);
}
});
}
}
html:
$('#searchTable').bootstrapTable({
columns: [{
field: 'product',
title: 'Produit'
} , {
field: 'language',
title: 'Langue'
}, {
field: 'comment',
title: 'Commentaire'
}],
showRefresh: true,
ajax: callbacker("whatEverValueYouWant"),
cache: false,
dataField: 'feedbacks',
totalField: 'total_size',
search: false,
sidePagination: 'server',
pagination: true
});

Select2 doesn't show the initSelection values

the jquery Select2(Version: 3.5.4) plugin doesn't show my initial value which I loaded on the initSelection function of the plugin. Here is my code:
$("#materialFieldTags").select2({
tags: true,
initSelection : function (element, callback) {
console.log(element);
console.log(callback);
var countryId = "3"; //Your values that somehow you parsed them
var countryText = "mater3";
var data = [];//Array
var tempJSONMat = {
materials: []
};
$.ajax({
url: "php/FormProcessing.php",
type: "post",
data: "main=" + "materialFault" + "&faultid="+ main.faultId,
dataType: 'json',
success: function(data){
data.forEach(function(column) {
//console.log(column);
tempJSONMat.materials.push({
"id" : column.material_id,
"text" : column.name
});
});
}
});
callback(tempJSONMat.materials[0]);
},
ajax: {
type: "POST",
url: 'php/FormFilling.php',
dataType: 'json',
data: function (params) {
return "main=" + "allMaterials" + "&searchterm=" + params;
},
processResults: function (data, page) {
return {
results: $.map(data, function (item) {
return {
text: item.name,
id: item.id
};
})
};
},
cache: true
}
});
Can you take I look at my code? Because I can't see it!! I also have try the:
$("#materialFieldTags").select2("data",mydata);
After the initialization of the plugin, but I am getting the same result.
Finally, I found my mistake! It was define two element by the same id, by mistake! The data appeared on first one and I was looking the second one.

Issues with jquery html()

Having some issues properly getting the manipulated data from an element.
Everywhere on the internet doesn't seem to cover such a simple question with a simple answer. Please help.
I have manipulated an element with a returning ajax request:
$("#last_comment_added").html("1457856458")
now my function on the page:
jQuery(document).ready(function($) {
var post_slug = $("#post_slug").html();
var last_comment_added = $("#last_comment_added").text();
if (post_slug && last_comment_added) {
setInterval(function() {
$.ajax({
type: "POST",
url: "ajax_comments.php",
data: {
"task": "updates",
"post_slug": post_slug,
"last_comment_added": last_comment_added
},
cache: false,
success: function(html) {
eval(html)
}
});
}, 10000);
}
});
I get the old data from the element, not the new ajax "1457856458" data.
Please help.
If I understand your problem right it's just that you create this variable called last_comment_added and expect it to be continually updated, you set it once to be the text of the last_comment_added, it's never updated in your interval function. Here's a change that should make it work better for you.
jQuery(document).ready(function($) {
var post_slug = $("#post_slug").html();
if (post_slug && last_comment_added) {
setInterval(function() {
$.ajax({
type: "POST",
url: "ajax_comments.php",
data: {
"task": "updates",
"post_slug": post_slug,
"last_comment_added": $("#last_comment_added").text()
},
cache: false,
success: function(html) {
eval(html)
}
});
}, 10000);
}
});
Don't use eval.
Try
$(document).ready(function() {
var post_slug = $("#post_slug").html();
var last_comment_added = $("#last_comment_added").html();
if (post_slug && last_comment_added) {
setInterval(_update, 10000);
}
});
function _update() {
$.ajax({
type: "POST",
url: "ajax_comments.php",
data: {
"task": "updates",
"post_slug": post_slug,
"last_comment_added": last_comment_added
},
cache: false,
success: function(data) {
$("#last_comment_added").html(data)
}
});
}
and you return from PHP only NEW data. (something like: echo '1457856458';)

Categories