Javascript array is empty when used in JSON.stringify - javascript

My project makes use of Dev Extreme and it's datagrid component. This datagrid displays data to my users where they can select individual rows on the datagrid and pass them to my backend via an API call.
In the API call, I need to pass over an array of values that I'm collecting from whichever row has been selected. When I output my array to the console, everything is how I expect it to be. Yet, when I place it in JSON.stringify() the array is empty.
Why does this happen? As I'm expecting the result to look like: { 'LoadContextIds': [1,2,3], "ReportingCobid": "20190119"}.
My logic for the above is as follows:
function runBatchWithLoadContexts() {
var data = [];
getDataGridInstance().getSelectedRowsData().done(function (rowData) {
for (var i = 0; i < rowData.length; i++) {
data.push(rowData[i].LoadContextId);
}
});
var obj = { 'LoadContextIds': data, "ReportingCobid": cobDate };
console.log(data);
console.log(JSON.stringify(obj));
}
And attached is a snippet from my console.log showing the above results as well. The top line is the output format of `data' and the bottom is the result of stringifying it.

From what I could tell (by briefly glancing at the devexterme docs), .done is asynchronous. So your for loop executes, and data array is filled, after your console logs. This explains why console.log(JSON.stringify(obj)); shows an empty array.
However, console logs actually print live objects, that can be updated as the objects themselves are updated. This explains why console.log(data); prints a non empty array.
I bet if you added console.log(JSON.stringify(data)), that too would be an empty array.

All that #junvar said is correct and if you create your obj inside the done function after the for loop, all the data is going to be there.
function runBatchWithLoadContexts() {
var data = [];
getDataGridInstance().getSelectedRowsData().done(function (rowData) {
for (var i = 0; i < rowData.length; i++) {
data.push(rowData[i].LoadContextId);
}
let obj = { 'LoadContextIds': data, "ReportingCobid": cobDate };
console.log(data);
console.log(JSON.stringify(obj));
});
}

Related

Data pass as objects as well as an array?

I'm developing a system for manage directors in group of companies. I need to filter directors for companies as assigned. After I pass data from controller to view, when selecting companies the filter shows incorrect results.
The above results will show when I console.log(this.directorships) those. I think it's because for single data it'll show as an array. But if those multiple it'll show as objects.
I'm looping those inside for loop as follows to print results.
for (let i = 0; i < this.directorships.length; i++) {
single_director = this.directorships[i].director_profile;
finalArray.push(single_director);
}
MyController.php
public function activeBoard($company_id){
$directorship = Directorship::with(['director_profile'])
->where('master_data_id',$company_id)
->get();
$active_directors = $directorship->where('active',1);
return $active_directors;
}
Can anyone please tell me what's the mistake I have done here? Or are there any methods to do what I expect?
It's hard to tell from the screenshots, but Objects in JavaScript are not iterable using a standard for loop, and don't have a length property by default. You should first check whether the directorships is an array, and then iterate or read suitably. For example:
let directorships_is_array = Array.isArray(directorships);
if(directorships_is_array) {
// ... loop through array
}
else {
// ... perform other function on object
}
There are a number of ways to iterate through an object, and get an objects length. The new for in loops can iterate through an object. For example:
for(let director in directorships) {
console.log(director);
}
You can also get the length of the Object using something like, let directors_length = Object.keys(directorships).length and then do something like this:
let number_of_directorships = Object.keys(directorships).length;
for(let i=0; i<number_of_directorships; i++) {
// ... iterate here
}
you need to use query like this you have initialize query before the condition
public function activeBoard($company_id){
$directorship = Directorship::where('master_data_id',$company_id)->where('active',1)->with('director_profile')->get();
return $directorship;
}

Why can't I push this additional data into my array?

I'm making an API call and here is the response
As you can see, key 0 & 1 have NULL for their 'outcome_status' whereas key 2 is populated. The number of returned results is dynamic
I wish to loop the results and push the 'category' & 'location' details into the array and if 'outcome_status' isn't NULL then I wish to add that data into the same array.
The problem is, within the IF statement that checks if outcome_status is null, I can't assign the forloop var i; variable as the key for
mapData where I use.push() the second time.
line:68 Uncaught TypeError: Cannot read property 'push' of undefined
var mapData = [];
function getPolApi(year,month,lat,lng,mapData) {
$.ajax({
url : "https://data.police.uk/api/crimes-at-location?date="+year+"-"+month+"&lat="+lat+"&lng="+lng,
type : "get",
async: false,
success : function(data) {
console.log(data);
mapData = [];// Empty the array of old results
for(var i = 1; i < data.length; i++) {
EDIT: I want to do this.
mapData.push([
data[i]['category'],
data[i]['location']['street']['name'],
data[i]['outcome_status']['category'],
data[i]['outcome_status']['date']
]);
But if there is no outcome_status then it will fail... So I added the second part into a conditional instead
if(data[i].outcome_status != null) {
//In order to access the original array by key,
// I wish to the use the forloop iteration otherwise
//mapData.push() will add the data as NEW arrays instead of adding on to the end of the existing arrays.
//Why can't I use the current index for the key here?
mapData[i].push([ //line 68
data[i]['outcome_status']['category'],
data[i]['outcome_status']['date'],
]);
}
heatmapData.push(new google.maps.LatLng(data[i].location.latitude,data[i].location.longitude));
}
console.log(mapData);
//Add results into view
for(var i = 0; i < mapData.length; i++) {
var fill = '<div class="row resu"><div class="col-xs-2 number"><h5>'+[i+1]+'</h5></div><div class="col-xs-10"><p class="text-primary">Type of crime: <span class="text-strong">'+mapData[i][0]+'</span></p><p class="text-primary">Location specifics: <span class="text-strong">'+mapData[i][1]+'</span></p></div></div>';
$('.output').append(fill);
}//endforloop
//Move the map into view of the heatmaps
moveMap(lat,lng);
//Add the heatmaps
addHeatMap();
// console.log(mapData);
},
error: function(dat) {
console.log('error');
}
});
Some issues:
Your for loop starts with i equal to one, so even after the first push, mapData[i] does not yet exist, so applying push to that makes no sense.
If you want to push additional elements to an existing array, you should not add those additional elements as part of an array, but provide them as separate arguments to push.
Furthermore, the code becomes a bit more functional when use array methods like map.
Here is how the part to fill mapData and heatmapData could look like:
// Create a new array, with nested arrays: one per data item
mapData = data.map(function (item) {
// Use a local variable to build the sub-array:
var arr = [
item.category,
item.location.street.name,
];
if (item.outcome_status) { // add 2 more elements if they exist
arr.push( // note: no square brackets here
item.outcome_status.category,
item.outcome_status.date,
);
}
// Add it to `dataMap` by returning it to the `map` callback:
return arr;
});
// Extend the heatmap with additional locations
heatmapData = heatmapData.concat(data.map(function (item) {
return new google.maps.LatLng(item.location.latitude,item.location.longitude);
}));
The Issue:
Here, you initialize i as 1:
for(var i = 1; i < data.length; i++) {
You then push one item to mapData[]:
mapData.push([
data[i]['category'],
data[i]['location']['street']['name'],
]);
A couple lines later, you try to access mapData[i]...
mapData[i].push([
data[i]['outcome_status']['category'],
data[i]['outcome_status']['date'],
]);
This is trying to access mapData[1], but mapData[] only has one item at this point. You need mapData[0].
The Solution:
Try simply changing your i to initialize as 0 instead of 1:
for(var i = 0; i < data.length; i++) {
If this is not sufficient and data[] needs to be a 1-index, then perhaps mapData[i-1] instead of mapData[i] would suit your needs.

How to store a Facebook Graph API response as a Javascript Array?

I'm wondering how to store the response from a Facebook API call into a Javascript array.
This is the call I'm making:
FB.api('/MYAPPID/scores/?fields=user', function(response) {
for (var i = 0; i < response.data.length; i++){
var grabbedarray = response.data[i].user.id;
console.log(grabbedarray);
}
})
The call FB.api('/MYAPPID/scores/?fields=user' returns a data set that has "name" and "id" properties for each element in the array, but I'm only interested in storing the "id" parts of the array.
The above code iterates through the response from the call, it checks user.id in each row of the array, and then the console.log shows the id for that row. This means that var grabbedarray is appearing several times in the console, showing a different id each time. I understand why this is happening, but I'm trying to get all the ids stored into one array, and then I'd like to console.log that.
So the final result in the console should be something like:
[456345624, 256456345, 253456435727, 376573835, 2652453245]
I've tried changing the call to FB.api('/MYAPPID/scores/?fields=user.id' in the hope that the response will show only a list of ids, but it's not working.
Does anyone have any idea how to solve this problem?
Thank you in advance!
To keep the approach you were using, you can push each new id you find into an array you define outside of the for loop.
var idArray = [];
FB.api('/MYAPPID/scores/?fields=user', function(response) {
for (var i = 0; i < response.data.length; i++){
idArray.push(response.data[i].user.id);
}
console.log(idArray);
})
You could also use map to transform the response array into what you want.
var idArray = [];
FB.api('/MYAPPID/scores/?fields=user', function(response) {
idArray = response.data.map(function(x){ return x.user.id });
console.log(idArray);
})

Javascript scope issue with jquery post and promise

I am trying to build an array from the responses of a jquery post. I have the following code:
categories_names = [];
$(categories).each(function(index, category_id) {
$.post('/modules/blog/add_post_categories', {post_id:result.result, category_id:$(category_id).val()},
function(result)
{
categories_names.push = result;
});
}).promise().done(function() {
var final_cats = categories_names.join("");
console.info(final_cats);
});
The post request inserts the category id into a table and returns the name of that category formatted like <li>Category Name here</li> so that once the array is built and all categories selected (by checkbox in the form previous to this) are entered into the database, the array can be joined and inserted as html to the final view. At the moment the code is just printing it out in the console as you can see but as you've probably guessed, it returns (an empty string)
I know this is most likely a scope issue since that's the area of javascript that still totally baffles me, so I'm hoping someone can shed some light on it.
Your .promise().done(...) isn't doing what you think it is. It's simply resolving instantly because there are no animations on the elements you are iterating over. Also, your syntax for [].push is wrong.
var defArr = $(categories).map(function(index, category_id) {
return $.post('/modules/blog/add_post_categories', {post_id:result.result, category_id:$(category_id).val()});
}).get();
$.when.apply(null,defArr).done(function() {
//var categories_names = [];
//for (var i = 0; i < arguments.length; i++) {
// categories_names.push(arguments[i][0]);
//}
var categories_names = $.map(arguments,function(i,arr) {
return arr[0];
});
var final_cats = categories_names.join("");
console.info(final_cats);
});
categories_names.push = result;
can you try changing this to
categories_names.push(result);
because push is a method, not a variable.

Issue with JSON stringify?

/* Helper function to clean up any current data we have stored */
function insertSerializedData(ids, type) {
// Get anything in the current field
current_data = $('#changes').val();
if (!current_data) {
var data = new Array();
data[type] = ids;
$('#changes').val(JSON.stringify(data));
} else {
var data = JSON.parse($('#changes').val());
data[type] = ids;
$('#changes').val(JSON.stringify(data));
}
console.log($('#changes').val());
}
I am using the following function to either add data to a current JSON object or create a new JSON object all together to be used in PHP later. Is the stringify() method only for FF? I am using google chrome and I am being given an empty object when using the conosole.log() function...
Also what happens if you try to store two values with the same key? I assume it will overwrite...so I should add a random math number at the end array in order to keep duplicates from showing up?
Thanks :)
These lines may cause problems:
var data = new Array();
data[type] = ids;
... because arrays in JavaScript are not quite like arrays in PHP. I suppose what you meant is better expressed by...
var data = {};
data[type] = ids;
Besides, current_data seems to be local to this function, therefore it also should be declared as local with var. Don't see any other problems... except that similar functionality is already implemented in jQuery .data() method.
UPDATE: here's jsFiddle to play with. ) From what I've tried looks like the array-object mismatch is what actually caused that Chrome behavior.
I reformatted it a bit, but and this seems to work. It will set the "value" attribute of the #changes element to a JSON string. I assume that the type argument is supposed to be the index of the array which you're trying to assign?
function insertSerializedData(ids, type) {
var changes = jQuery('#changes'), arr, val = changes.val();
if (!val) {
arr = [];
arr[type] = ids;
changes.val(JSON.stringify(arr));
} else {
arr = JSON.parse(val);
arr[type] = ids;
changes.val(JSON.stringify(arr));
}
console.log(changes);
}

Categories

Resources