Cant access Javascript multidimensional array - javascript

I have seen many of these questions on here but none seem to solve my problem. I have a multidimensional (nested) array which I am populating through query. I wish to send the final array over AJAX jQuery:
(function() {
var orderDetails = [];
orderDetails['retailer'] = [];
orderDetails['order'] = [];
db.transaction(function(qry){
qry.executeSql("SELECT * FROM retailers WHERE pending = '1' ", [], function(tx, results){
len = results.rows.length; //if rows.length, means retailer is pending so add details to array. If no length, means retailer exists
for (var i=0; i<len; i++){
console.log('start '+i+' loop in retailers qry');
orderDetails['retailer'][i] = [];
orderDetails['retailer'][i]['localID'] = results.rows.item(i).ID;
orderDetails['retailer'][i]['retailerName'] = results.rows.item(i).retailerName;
orderDetails['retailer'][i]['address'] = results.rows.item(i).address;
orderDetails['retailer'][i]['postcode'] = results.rows.item(i).postcode;
console.log('finish '+i+' loop in retailers qry');
}
}, function(err){console.log(err)})
}
This is how I am populating the array, and here is the AJAX request:
function(){
console.log('start orders qry success callback');
//alert(orderDetails['retailer'][0]['localID']);
var st = JSON.stringify(orderDetails['retailer']);
console.log(st);
$.ajax({//send retailer to server, bring back the ID of the retailer as it is on the server so we can insert it into the order
type: "POST",
cache: false,
//async: false,
url: "https://www.......processOrder.php",
data: { orderType: 'saved', orderDetails: st},
dataType: "json",
success: function(result){
}
})
});
When I log the above just before the ajax request, it returns [[],[],[],[],[],[],[],[],[],[],[]] so I know something is working, I just thought the whole contents of the object would be visible on the server side.
Also I have wrapped the whole thing in an anonymous function because I think this helps the array variable scope.

Change this orderDetails['retailer'][i] = []; to this orderDetails['retailer'][i] = {};
And if your item is not a function you want to call with parameter i, access it like this: results.rows.item[i].ID

Related

Issues sending selected rows values into a controller MVC

I'm trying to send the selected rows into a controller when I click on the button with id="send". The issue is that when I tried to send other values( in this case a number and a string) with the selected rows values, the selected rows values is sending null to the controller but the number and the string aren't null in the controller parameters.
This is my javascript code that works fine if only i send the selected rows values:
$('#send').click(function () {
var items = {};
var grid = $('#grid').data('kendoGrid');
var selectedElements = grid.select();
for (var j = 0; j < selectedElements.length; j++) {
var item = grid.dataItem(selectedElements[j]);
items['grid[' + j + '].ParecidoCodigo'] = item.ParecidoCodigo;
}
$.ajax({
url: '#Url.Action("Index", "Busqueda")',
type: "POST",
async: false,
data: items,
success: function (result) {
console.log(result);
}
})
})
and this is my controller method action:
public ActionResult Index(MarcaParecido[] grid)
{ ... }
Everything works fine until now.But when I tried to send another values like this:
$('#send').click(function () {
var items = {};
var grid = $('#grid').data('kendoGrid');
var selectedElements = grid.select();
var enviarDest = $('#destinatario').val();
var marca = $('#numMarca').val();
for (var j = 0; j < selectedElements.length; j++) {
var item = grid.dataItem(selectedElements[j]);
items['grid[' + j + '].ParecidoCodigo'] = item.ParecidoCodigo;
}
$.ajax({
url: '#Url.Action("Index", "Busqueda")',
type: "POST",
async: false,
data: { items, marcas: marca, destinatario: enviarDest },
success: function (result) {
console.log(result);
}
})
})
The selected rows values is sending me null, but the others values aren't null
This is my controller now:
public ActionResult Index(MarcaParecido[] grid, string marcas, string destinatario)
{...}
I tried with JSON.stringify too but it doesn't work.
If items is a collection of the key/value pairs that you are sending to the server, add the two additional parameters to that, and then continue to send item the items object. MVC should read the "grid." items as the list of items in the collection (as you have working now), and see the other two parameters in the variables you have specified:
items["marcas"] = marca;
items["destinatario"] = enviarDest;
$.ajax({
.
.
data: items

Retrieve list items from multiple lists with urls stored in an array

How do i get list items from different lists in SharePoint using javascript. Given that all my list are stored in an array. And I need to loop through the array and execute similar functions on each list.
function initializePage() {
listcollections.forEach(function (value, index) { // listcollections is the array that contains the list url for different lists
var listtitle = value.listTitle;
var siteUrl = value.siteURL;
getItemsWithCaml(siteUrl, listtitle,
function (camlItems) {
var listItemEnumerator = camlItems.getEnumerator();
while (listItemEnumerator.moveNext()) {
var EventsItem = new Events();
var listItem = listItemEnumerator.get_current();
EventsItem.eventTitle = listItem.get_item('Title');
EventsItem.eventDate = listItem.get_item('EventDate');
EventsItem.eventId = listItem.get_id();
EventsItem.eventSite = siteUrl;
EventsItem.eventList = listtitle;
EventsCollection.push(EventsItem);
}
},
function (sender, args) {
alert('An error occurred while retrieving list items:' + args.get_message());
});
})
};
function getItemsWithCaml(siteUrl, listtitle, header, success, error)
{
var hostWebContext = new SP.ClientContext(siteUrl);
var list = hostWebContext.get_web().get_lists().getByTitle(listtitle);
var caml = new SP.CamlQuery();
//Create the CAML that will return only items expiring today or later
caml.set_viewXml("<View><Query><Where><Geq><FieldRef Name=\'Expires\'/><Value Type=\'DateTime\'><Today /></Value></Geq></Where> </Query></View>");
var camlItems = list.getItems(caml);
hostWebContext.load(camlItems);
hostWebContext.executeQueryAsync(
function () {
success(camlItems);
},
error
);
};
//need to execute certain functions to format each list item
// I am not able to retrieve all list items in a single variable to be able to display data from all lists together
In the example below, I create a JavaScript object named ListDataCollection that contain a property Lists that is an array of objects.
Each of those contain a Url property whit the url of the lists I want to get the content.
Then I loop trough the array of objects and call the Sharepoint REST api for each Url.
Each time a call is complete :
I create a Data property on the current object with the data received
by the ajax call to the REST api.
I also update the current object Completed property to true.
Then I call a function named ifAllCompleted that check if all ajax calls are ended.
When all data is received, I log the word Completed on the browser console.
At this point, you have an array of objects. Each object contains the data of one Sharepoint list.
For example :
ListDataCollection.Lists[0].Data.d.results[0].Title
will contain the value of the Title Column of the first element in the first list.
If you want, you can merge all data in one array using the concat function in JavaScript.
Look at the 4 lines of code following the word Completed.
Hope this can help!
<script>
var ListDataCollection = {
Lists:[{
Url:"http://Url.Of.Your.Site.Collection/_api/web/lists/getbytitle('List1')/Items",
Completed:false
},{
Url:"http://Url.Of.Your.Site.Collection/_api/web/lists/getbytitle('List2')/Items",
Completed:false
},{
Url:"http://Url.Of.Your.Site.Collection/_api/web/lists/getbytitle('List3')/Items",
Completed:false
}]
};
function ifAllCompleted() {
for (var i=0;i<ListDataCollection.Lists.length;i++) {
if (!ListDataCollection.Lists[i].Completed) {
return false;
}
}
console.log('Completed');
var arrayOfAllData = ListDataCollection.Lists[0].Data.d.results;
arrayOfAllData = arrayOfAllData.concat(ListDataCollection.Lists[1].Data.d.results);
arrayOfAllData = arrayOfAllData.concat(ListDataCollection.Lists[2].Data.d.results);
console.log('Total elements : ' + arrayOfAllData.length);
}
$(document).ready(function(){
for (var x=0;x<ListDataCollection.Lists.length;x++) {
$.ajax({
url:ListDataCollection.Lists[x].Url,
indexValue:x,
method: "GET",
headers: { "Accept": "application/json; odata=verbose" },
success: function (data, status, xhr) {
ListDataCollection.Lists[this.indexValue].Data = data;
ListDataCollection.Lists[this.indexValue].Completed = true;
ifAllCompleted();
},
error: function (xhr, status, error) {
console.log('error');
}
});
}
});
</script>

Collect AJAX results in order

I have an array of values (myarray), that I want to iterate through and run an AJAX request on each iteration. I've put each ajax request inside another array (requests), so that I can call an alert when all AJAX requests have completed:
Like so:
var requests = [];
for (i = 0; i < myarray.length; ++i) {
requests.push($.ajax({
url: 'anotherurl?=' + myarray[i],
dataType: "JSONP",
success: function (data) {
array_of_results.push(data);
}
}));
}
$.when.apply($, requests).done(function() {
alert('complete');
});
All the results are collected in array_of_results. However due to the AJAX requests taking different lengths of time to complete, this array doesn't have the results in the original order.
Is there any way to order this array?
I hope I've made sense. I appreciate this is quite convoluted.
Have you tried the following? I think this should work. All the responses should be available, in order, in the success function of the when().
var requests = [];
for (i = 0; i < myarray.length; ++i) {
requests.push($.ajax({
url: 'anotherurl?=' + myarray[i],
dataType: "JSONP"
}));
}
$.when.apply($, requests).done(function() {
array_of_results = arguments;
alert('complete');
});
Instead of using a loop consider using recursion. Here's a complete example:
var myArray = [
"somevalue",
"some other value",
"another value"
];
var i = myArray.length;
var responses = [];
function doRequests(){
i--;
$.ajax({
url: "myurl.php",
data: {paramname: myArray[i]}
}).done(function(response){
responses.push(response);
if(i>0) doRequests();
else{
// all requests sent.. do stuff
// responses array is in order
console.log(responses);
alert("all done!");
}
});
}
You can add a custom attribute to your $.ajax object, setted to your i var.
var requests = [];
for (i = 0; i < myarray.length; ++i) {
requests.push($.ajax({
url: 'anotherurl?=' + myarray[i],
dataType: "JSONP",
myCustomIndex: i,
success: function (data) {
array_of_results[this.myCustomIndex] = data;
}
}));
}
$.when.apply($, requests).done(function() {
alert('complete');
});
JavaScript is really permisive, if you attribute a value to an array out of its bounds (higher than 0), the size of the array will be automaticaly set to the right amount.
How about using jquery.ajax call with async setting as false. This way the reaponse will be in order as requested...
Building on #Christo's answer - using arrays map function
var array_of_results = [];
var requests = myarray.map(function(item, index) {
return $.ajax({
url: 'anotherurl?=' + item,
dataType: "JSONP",
success: function (data) {
array_of_results[index] = data;
}
}
});
...

How to deal with a group of deferred's when one of them fails

I have a series of ajax calls that fill columns on a page.
var doneDefers = function(defer) {
// leftColDefer is another deferred that sets some header info
$.when(defer, leftColDefer).done(function(req1, req2){
var data = req1[0],
head = req2[0];
// spit this data out to elements on the page
});
};
for(i=0;i<window.ids.length;i++){
defer[i] = $.ajax({
url: 'api/get_runs_stats.php',
type: 'GET',
dataType: 'json',
data: {
run_id: window.ids[i]
}
});
doneDefers(defer[i]);
}
This works fine. If an ajax call fails, nothing is spit out and all is right with the world.
Now I want to do some calculations based on all the data that got spit out.
$.when.apply(null, defer)
.done(function() {
var args = Array.prototype.slice.call(arguments);
calcDeltas();
})
.fail(function() {
var args = Array.prototype.slice.call(arguments);
console.log('in list fail');
});
The done function works fine none of the ajax calls fail. If one of them fail, I go into the fail function and I don't have access to any of the return data from the other runs. The arguments array only has the failed call's data.
I would like to do my calculations on the data sets that passed. How can I get to the data from the good calls when one of them fails?
I'm not sure this is the simplest solution but it stands a chance of working.
var ajax_always_promises = [],//to be populated with promises that (barring uncaught error) are guaranteed to be resolved.
data_arr = [],//an array to be (sparsely) populated with asynchronously delivered json data.
error_arr = [];//an array to be (sparsely) populated with ajax error messages.
$.each(window.ids, function(i, id) {
var dfrd = $.Deferred();
var p = $.ajax({
url: 'api/get_runs_stats.php',
type: 'GET',
dataType: 'json',
data: {
run_id: window.ids[i]
}
}).done(function(json_data) {
data_arr[i] = json_data;//intentionally not `data_arr.push(json_data);`
}).fail(function(jqXHR, textStatus, errorThrown) {
error_arr[i] = textStatus;//intentionally not `error_arr.push(textStatus);`
}).always(dfrd.resolve);
ajax_always_promises[i] = dfrd.promise();
doneDefers(p);
});
$.when.apply(null, ajax_always_promises).done(function() {
//The data in the (sparsely) populated arrays `data_arr` and `error_arr` is available to be used.
var i, id, success_count=0, error_count=0;
for(i=0; i<Math.max(data_arr.length,error_arr.length); i++) {
//Here, the index i corresponds to the original index of window.ids ...
//...that's the advantage of sparsely populating the arrays.
id = window.ids[i];
if(data_arr[i]) {
//Here, do whatever is required with `data_arr[i]`, and `id` if needed.
success_count++;
}
else if(error_arr[i]) {
//Here, do whatever is required with `error_arr[i]`, and `id` if needed.
error_count++;
}
}
console.log("Success:errors: " + success_count + ':' + error_count);
});
Untested - may well need debugging

Append Order - jQuery

I am trying to get the string to order by how it is displayed (red,blue,orange,black). For some reason, it will append the order randomly. For Example: it would output (blue,orange,red,black). Any help would be great. Thanks.
var tCookie = "red,blue,orange,black";
var Cookies = tCookie.split(',');
if (Cookies) {
for (var i = 1; i <= Cookies.length; i++) {
var dataString = "TabId="+Cookies[i]+"";
$.ajax({
type: "POST",
url: "includes/tab.php",
data: dataString,
cache: false,
success: function(html){
$("#Dynamic_Tab").append(html).children(':last').hide().fadeIn("fast");
}
});
}
}
You could have a list of requests and responses, and start appending when all are done, so that the order is always correct:
var deferreds = [],
results = [];
for (var i = 1; i <= Cookies.length; i++) {
(function(i) { // to freeze i
var dataString = "TabId="+Cookies[i]+"";
deferreds.push($.ajax({
type: "POST",
url: "includes/tab.php",
data: dataString,
cache: false,
success: function(html){
results[i] = html; // insert at the synchronous position
}
}));
})(i);
}
$.when.apply($, deferreds).then(function() {
$.each(results, function(i, html) {
$("#Dynamic_Tab").append(html).children(':last').hide().fadeIn("fast");
});
});
You can use deferred objects here to only append the HTML after all of the AJAX requests come back:
//create array to store XHR objects that will resolve when the AJAX requests return
//also create an object to store the AJAX responses
var jqXHRs = [],
responses = {};
//iterate through each of the cookie indexes
$.each(cookies, function (index, value) {
//create the dataString and cache the value of this index so it can be used in the success callback for the AJAX request associated with this index
var dataString = "TabId=" + value,
thisValue = value;
//store an empty string in the output variable for the current index, this keeps it's place in-line
responses[thisValue] = '';
//do the AJAX request and store it's XHR object in the array with the rest
jqXHRs[jqXHRs.length] = $.ajax({
type : "POST",
url : "includes/tab.php",
data : dataString,
cache : false,
success : function (html) {
//now that the AJAX request has returned successfully, add the returned HTML to the output variable for this index
responses[thisValue] = html;
}
});
});
//wait for all of the XHR objects to resolve then add all the HTML to the DOM
$.when(jqXHRs).then(function () {
//all of the AJAX requests have come back and you can now add stuff to the DOM
var $element = $("#Dynamic_Tab");
$.each(responses, function (index, value) {
$element.append(value).children(':last').hide().delay(index * 250).fadeIn(250);
}
});
The .delay() is so that each new row will fade in, in order.

Categories