Can't iterate into javascript array of objects - javascript

I come to you because i have some issues using javascript arrays.
I'm trying to iterates through a javascript array filled with some objects.
I have totally 4 objects.
this is my code :
// sort trainings_tab descending order
trainings_tab = trainings_tab.sort(function(a, b) {
if (a.date_from < b.date_from)
return 1;
else if(a.date_from > b.date_from)
return -1;
return 0;
});
console.log(trainings_tab);
for(var h = 0; h < trainings_tab.length; h++) {
// var training = new_array[h];
console.log(trainings_tab[h]);
}
and what i've got from console.log(trainings_tab); =>
[] (i have a little blue i here that say : object value at left was snapshotted when logged value below was evaluated just now)
0: Object
_geoloc: Object
_highlightResult: Object
_rankingInfo: Object
address: "Hospital da plastica, Rio de Janeiro, Brazil"
address_id: 16623
date_from: "1479769200"
date_to: "1480028400"
device: "USD"
doctor_full_name: "John Doe"
doctor_id: "85"
doctor_image: "/images/avatar_85.jpg"
doctor_url: "/profile/85"
guest: "2"
labo_id: "8So7KJPmv4qyL2uHD"
langues: "English"
objectID: "689"
objectives: Array[2]
price: "1000"
procedures: Array[1]
products: Array[1]
seat_left: "2"
seat_taken: 0
speciality: "PLASTIC SURGERY, BODY CONTOURING"
training_full: ""
training_name: "Lipofacillomaxial"
url: "/training/detail/689"
__proto__: Object
1: Object
2: Object
3: Object
length: 4
__proto__: Array[0]
Each objects looks like the first one, with other datas ofc.
But the problem is that my for loop doesn't iterate other the array and i can't see the console.log(trainings_tab[h]);
Someone has an idea and can help me plz ? Thanks.
EDIT : HOW DO I POPULATE MY TAB ?
i assign a var at empty tab :
var trainings_tab = [];
I use ALGOLIA (https://www.algolia.com/) to search into an index called 'training' and that get all my records. When the search is done i have a callback and i'm doing this :
function searchDone(err, content) {
if (err) {
console.error(err);
return;
}
//console.log(content.hits);
for(var i = 0; i < content.hits.length; i++) {
var training = content.hits[i];
// check that's a training
if (training && training.date_from != null) {
// calculate seats taken
var seats_taken = training.guest - training.seat_left;
var training_full = '';
// training is full ?
if (training.seat_left == 0) training_full = 'training-full';
training.seat_taken = seats_taken;
training.training_full = training_full;
if (training.hidden == false || training.hidden == null)
Session.set("countTrainings", Session.get("countTrainings")+1);
trainings_tab.push(training);
}
}
}
It seems that my problem is when i populate the trainings_tab, because if i console.log before the sort, i have the same display than quoted before...

Related

How do i save multiple objects into an array

I have this object after click the save button.
{description: "ghhg", dateSelected: "2020-02-27", startDate: "2020-02-27", company_id: "2", hr_id:
72, …}
But whenever i click on save, it gives me a new object instead of storing it in array.
The question is how can i store each object inside an array to get
[
{description: "ghhg", dateSelected: "2020-02-27", startDate: "2020-02-27", company_id: "1" …},
{description: "grrrhhg", dateSelected: "2020-03-27", startDate: "2020-03-27", company_id: "2" …},
{description: "ghrtrhg", dateSelected: "2020-04-27", startDate: "2020-04-27", company_id: "2",  …},
.
.
.
]
This is my code
saveHolidays(hols : []){
this.holidays.hr_id = this.hrID.id;
this.getHolidayDate = this.holidays.dateSelected.split(" to ");
this.holidays.startDate = this.getHolidayDate[0];
this.holidays.endDate = this.getHolidayDate[1];
this.getHols = this.holidaysData;
this.holiday_date = [];
this.holidaysArray = [];
var tempHolidays = [];
this.getHols.forEach((element,key) => {
if(element.startDate){
this.holiday_date.push({startDate : element.startDate, endDate : element.endDate, company_id :
element.company_id})
}
});
var getElement = [];
let getStartDate = this.holiday_date.map(element => {
getElement.push(element.startDate, element.company_id);
return getElement;
});
for(var i = 0; i < getStartDate.length; i++){
var isStartDatePresent = getStartDate[i].includes(this.holidays.startDate);
var isCompanyIdPresent = getStartDate[i].includes(+this.holidays.company_id);
}
if(isStartDatePresent == true && isCompanyIdPresent == true ){
this.snotifyService.error('Holiday Already Exist');
}else{
hols = this.holidays;
for(var i = 0; i < hols.length; i++){
this.holidaysArray.push(hols[i]);
}
return this.holidaysArray
}
}
I'm a bit rusty, but if I remember correctly, JS arrays don't have fixed widths, so you might be able to push each saved holiday to an externally instantiated array or return one and set the desired external array to it.
You are reinitializing your array every time you click on save button by writing this.holidaysArray.
Removing it might solve your problem.
Set this.holidaysArray to an array ONLY IF it not already an Array.
/* REPLACE */
this.holidaysArray = []
/* WITH */
if (!Array.isArray(this.holidaysArray)) {
this.holidaysArray = []
}
Also, I highly recommend using a test-framework like Jest to test your code.
Good Luck...

$localStroage array doesn't match $scope array

I am pushing Objects to a $localStorage array for persistence. I also check this array to see if an object is present before adding / removing an Object (if present it should splice if not present then it will push).
When I refresh my page the data returned from $localStorage doesn't seem to be the same as it was pre-refresh as my check function doesn't work, despite it looking EXACTLY the same on inspection.
Objects being pushed are structured like this:
{
"createdAt": "2015-04-24T10:21:21.649Z",
"difficulty": "Hard",
"exerciseDescription": "Lie on your back on a bench and take hold",
"exerciseID": "3101",
"exerciseName": "Bench Press",
"images": [8679, 8680, 8682],
"tags": ["Barbell", "Horizontal Flexion", "Extension", "Strength", "Chest", "Triceps", "Shoulder", "Elbow, Wrist & Hand"],
"updatedAt": "2015-09-09T20:14:59.681Z",
"words": ["bench", "press", "chest"],
"objectID": "ak6t7ukQdY",
"_highlightResult": {
"exerciseName": {
"value": "Bench Press",
"matchLevel": "none",
"matchedWords": []
}
}
}
Check if object if present (toggle add/remove)
$scope.addExerciseToProgramme = function(exercise) {
if (!$localStorage.Programme) {
$localStorage.Programme = [];
}
var index = $localStorage.Programme.indexOf(exercise);
if (index > -1) {
$localStorage.Programme.splice(index, 1);
} else {
$localStorage.Programme.push(exercise);
}
}
Function to watch/load $localStorage
$scope.$watch(function() {
return $localStorage.Programme
}, function(programme) {
$scope.programme = programme;
});
ng-class to check if exercise is in programme
<i class="exercise-add-indicator ion-ios-checkmark-outline" ng-class="{'orange': programme.indexOf(exercise) > -1}"></i>
Problem
There are two problems with this:
Following refresh, the ng-class doesn't conditionally add the class depending on the content of my $scope.programme
The addExerciseToProgramme function doesn't respect the indexOf check and pushes the exercise object to the array regardless!
Array.prototype.indexOf() uses strict equality: An expression comparing Objects is only true if the operands reference the same Object.
You shouldn't use this when working with localStorage.
When saving an object to localStorage it's turned into a string. When retrieved it's turned into an object again.
This will however be a new object, even if it looks exactly the same.
For example, this will yield false:
var object1 = { id: 1 };
var object2 = { id: 1 };
console.log(object1 === object2);
To get it working you can implement a custom function that retrieves the index based on the value of a property of your choosing. Note that it should be unique.
For example:
$scope.getExerciseIndex = function(exercise) {
var index = -1;
if (!$scope.programme) return index;
for (var i = 0; i < $scope.programme.length; i++) {
if ($scope.programme[i].exerciseID !== exercise.exerciseID) continue;
index = i;
break;
}
return index;
};
$scope.exerciseExists = function(exercise) {
var index = $scope.getExerciseIndex(exercise);
return index > -1;
};
$scope.addExerciseToProgramme = function(exercise) {
if (!$localStorage.Programme) {
$localStorage.Programme = [];
}
var index = $scope.getExerciseIndex(exercise);
if (index > -1) $localStorage.Programme.splice(index, 1);
else $localStorage.Programme.push(exercise);
};
HTML:
... ng-class="{'orange': exerciseExists(exercise) }" ...
Demo: http://plnkr.co/edit/R6TEisvQ7gkDcwBgw0D1?p=preview

how to increase custom count in jquery json

If laptop model and serial id are same, i've to add new field totalModel and increase count. For example in below case: serialid "1" and laptop model "xyz" are coming two time so i want to add "totalModel" count as 2 and so on. How can i achieve this in jquery
This question is not really about jQuery, it is about mapping and filtering arrays and objects. However, we can use some jQuery convenience methods to solve it.
A large part of solving these problems is by properly defining what you want to do. It sounds from your question that you want to get a map of unique serial ids per laptop model type. We can use JavaScript's Array.prototype.reduce to produce just such a map (Note that we will take the 'sold' value for the first of each laptop model we encounter):
var laptop_models = data.reduce(function (memo, obj) {
if (!memo[obj.laptopModel]) {
memo[obj.laptopModel] = {
unique_serial_ids: [],
sold: obj.sold
};
}
if ($.inArray(obj.serialid, memo[obj.laptopModel].unique_serial_ids) === -1) {
memo[obj.laptopModel].unique_serial_ids.push(obj.serialid);
}
return memo;
}, {});
Next, we can map our laptop_models object into the array you specified as your expected result:
var result = $.map(laptop_models, function (laptop_model, model_name) {
return {
laptopModel: model_name,
totalModel: laptop_model.unique_serial_ids.length,
sold: laptop_model.sold
};
});
You got the idea already. Iterate through the array.
if them item is in a hash, increment the count, otherwise, add to the hash and set the count to 1
var hash = {};
for (var i = 0;i<data.length;i++) {
if (hash[data[i].laptopModel) {
hash[data[i].laptopModel]++;
}
else
hash[data[i].laptopModel] = 1;
}
var data = [
{
"serialid": 1,
"laptopModel": "xyz",
"sold": "yes",
"cnt": 5
},
{
"serialid" :1,
"laptopModel": "xyz",
"sold": "yes",
"cnt": 4
},
{
"serialid": 1,
"laptopModel": "abc",
"sold": "yes",
"cnt": 3
},
{
"serialid": 3,
"laptopModel": "xyz",
"sold": "yes",
"cnt": 2
}];
var result = []; //work if result = {};
var tempArray = []; // used to store unique name to prevent complex loop
data.forEach(function(item){
if($.inArray(item.laptopModel, tempArray)< 0){// unique name
result.push(formatData(item));
tempArray.push(item.laptopModel);
}
else{
var indexNew = $.inArray(item.laptopModel, tempArray);
result[indexNew]["totalModel"] += 1;
}
});
function formatData(item){
return{
"laptopModel": item.laptopModel,
"sold": item.sold,
"totalModel": 1
}
}
alert(JSON.stringify(result)); //expect array 2 item but it's empty array
console.log(result); //Will have result 2 item when I view console window
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Loop Through JSON, Insert Key/Value Between Objects?

UPDATE - Thanks for all the great answers and incredibly fast response. I've learned a great deal from the suggested solutions. I ultimately chose the answer I did because the outcome was exactly as I asked, and I was able to get it working in my application with minimal effort - including the search function. This site is an invaluable resource for developers.
Probably a simple task, but I can't seem to get this working nor find anything on Google. I am a Javascript novice and complex JSON confuses the hell out of me. What I am trying to do is make a PhoneGap Application (Phone Directory) for our company. I'll try to explain my reasoning and illustrate my attempts below.
I have JSON data of all of our employees in the following format:
[
{
"id":"1",
"firstname":"John",
"lastname":"Apple",
"jobtitle":"Engineer"
},
{
"id":"2",
"firstname":"Mark",
"lastname":"Banana",
"jobtitle":"Artist"
},
... and so on
]
The mobile framework (Framework 7) that I am using offers a "Virtual List" solution which I need to take advantage of as our directory is fairly large. The virtual list requires you to know the exact height of each list item, however, you can use a function to set a dynamic height.
What I am trying to do is create "headers" for the alphabetical listing based on their last name. The JSON data would have to be restructured as such:
[
{
"title":"A"
},
{
"id":"1",
"firstname":"John",
"lastname":"Apple",
"jobtitle":"Engineer"
},
{
"title":"B"
},
{
"id":"2",
"firstname":"Mark",
"lastname":"Banana",
"jobtitle":"Artist"
},
... and so on
]
I've been able to add key/value pairs to existing objects in the data using a for loop:
var letter, newLetter;
for(var i = 0; i < data.length; i++) {
newLetter = data[i].lastname.charAt(0);
if(letter != newLetter) {
letter = newLetter
data[i].title = letter;
}
}
This solution changes the JSON, thus outputting a title bar that is connected to the list item (the virtual list only accepts ONE <li></li> so the header bar is a div inside that bar):
{
"id":"1",
"firstname":"John",
"lastname":"Apple",
"jobtitle":"Engineer",
"title":"A"
},
{
"id":"1",
"firstname":"Mike",
"lastname":"Apricot",
"jobtitle":"Engineer",
"title":""
}
This solution worked until I tried implementing a search function to the listing. When I search, it works as expected but looks broken as the header titles ("A", "B", etc...) are connected to the list items that start the particular alphabetical section. For this reason, I need to be able to separate the titles from the existing elements and use them for the dynamic height / exclude from search results.
The question: How can I do a for loop that inserts [prepends] a NEW object (title:letter) at the start of a new letter grouping? If there is a better way, please enlighten me. As I mentioned, I am a JS novice and I'd love to become more efficient programming web applications.
var items = [
{ "lastname":"Apple" },
{ "lastname":"Banana" },
{ "lastname":"Box" },
{ "lastname":"Bump" },
{ "lastname":"Can" },
{ "lastname":"Switch" }
];
var lastC = null; //holds current title
var updated = []; //where the updated array will live
for( var i=0;i<items.length;i++) {
var val = items[i]; //get current item
var firstLetter = val.lastname.substr(0,1); //grab first letter
if (firstLetter!==lastC) { //if current title does not match first letter than add new title
updated.push({title:firstLetter}); //push title
lastC = firstLetter; //update heading
}
updated.push(val); //push current index
}
console.log(updated);
Well right now you have an array of objects - prefixing the title as its own object may be a bit confusing - a better structure may be:
[
{
title: "A",
contacts: [
{
"id":"1",
"firstname":"John",
"lastname":"Apple",
"jobtitle":"Engineer",
"title":"A"
}
]
Given your current structure, you could loop and push:
var nameIndexMap = {};
var newContactStructure = [];
for (var i = 0; i < data.length; i++) {
var letter = data[i].lastname.charAt(0);
if (nameIndexMap.hasOwnProperty(letter)) {
//push to existing
newContactStructure[nameIndexMap[letter]].contacts.push(data[i])
} else {
//Create new
nameIndexMap[letter] = newContactStructure.length;
newContactStructure.push({
title: letter,
contacts: [
data[i]
]
});
}
}
newContactStructure will now contain your sorted data.
Demo: http://jsfiddle.net/7s50k104/
Simple for loop with Array.prototype.splice will do the trick:
for (var i = 0; i < data.length; i++) {
if (i == 0 || data[i-1].lastname[0] !== data[i].lastname[0]) {
data.splice(i, 0, {title: data[i].lastname[0]});
i++;
}
}
Demo. Check the demo below.
var data = [
{"lastname":"Apple"},
{"lastname":"Banana"},
{"lastname":"Bob"},
{"lastname":"Car"},
{"lastname":"Christ"},
{"lastname":"Dart"},
{"lastname":"Dog"}
];
for (var i = 0; i < data.length; i++) {
if (i == 0 || data[i-1].lastname[0] !== data[i].lastname[0]) {
data.splice(i, 0, {title: data[i].lastname[0]});
i++;
}
}
alert(JSON.stringify( data, null, 4 ));

How to navigate in nested JSON

I have nested JSON object like
{"baseball":
{"mlb":
{"regular":
{"_events": [{"start_time": "2011-07-31 17:35", "lines":
[{"comment": "", "coeff": "2.35", "title": "2", "old_coeff": "2.35", "is_main": true},
{"comment": "", "coeff": "1.59", "title": "2", "old_coeff": "1.59", "is_main": true},
{"comment": "", "coeff": "1.59", "title": "2", "old_coeff": "1.59", "is_main": true},
{"comment": "", "coeff": "2.35", "title": "2", "old_coeff": "2.35", "is_main": true}],
"members": ["atlanta", "florida"]
}
]
}}}}
And i need get _events array and parse it too. But I don't know what will be in cells before _events and how they will. How do I work with this structure?
function recursiveGetProperty(obj, lookup, callback) {
for (property in obj) {
if (property == lookup) {
callback(obj[property]);
} else if (obj[property] instanceof Object) {
recursiveGetProperty(obj[property], lookup, callback);
}
}
}
And just use it like this:
recursiveGetProperty(yourObject, '_events', function(obj) {
// do something with it.
});
Here's a working jsFiddle: http://jsfiddle.net/ErHng/ (note: it outputs to the console, so you need to Ctrl+Shift+J/Cmnd+Option+I in chrome or open firebug in Firefox and then re-run it)
If the structure is known:
Assuming that you have the above in a String called input (and that the JSON is valid):
var obj = JSON.parse(input) // converts it to a JS native object.
// you can descend into the new object this way:
var obj.baseball.mlb.regular._events
As a warning, earlier versions of IE do not have JSON.parse, so you will need to use a framework for that.
If the structure is unknown:
// find the _events key
var tmp = input.substr(input.indexOf("_events"))
// grab the maximum array contents.
tmp = tmp.substring( tmp.indexOf( "[" ), tmp.indexOf( "]" ) + 1 );
// now we have to search the array
var len = tmp.length;
var count = 0;
for( var i = 0; i < len; i++ )
{
var chr = tmp.charAt(i)
// every time an array opens, increment
if( chr == '[' ) count++;
// every time one closes decrement
else if( chr == ']' ) count--;
// if all arrays are closed, you have a complete set
if( count == 0 ) break;
}
var events = JSON.parse( tmp.substr( 0, i + 1 ) );
The easiest thing to do in this situation, I find, is to go to JSFiddle, paste in your json as a variable:
var json = {"baseball": ... etc.
console.log(json);
Then using Chrome, "View" -> "Developer" -> "Javascript console" start to experiment with what the data structure looks like in order to build up your parsing function.
Then start experimenting with the structure. Eg.
console.log(json.baseball.mlb.regular._events);
Or if you turn on JQuery:
$.each(json.baseball.mlb.regular._events, function(i, item){
$.each(item.lines,function(i,line){
console.log(line.coeff);
});
});
If you're having trouble actually loading in this JSON into a variable you'll need to JSON.parse a string retrieved via an AJAX call I suspect.

Categories

Resources