AngularJS - grabbing specific data from an JSON array - javascript

Here is a picture of what the API is returning:
I am trying to create variables that grab the "Current Approver" and "Status" from this array. And if the "Current Approver" matches the username stored in local storage and the "Status" is "REJECTED" then I want to run a line of jquery.
Here is what I have:
$http.get( API + '/car' ).
success(function(data) {
$scope.myCars = data;
console.log(data);
var originator = $scope.myCars["My CARs"]["Current Approver"],
status = $scope.myCars["My CARs"].Status,
user = localStorage.getItem('user') || null
// Check if logged in user is originator and CAR is "REJECTED"
if (originator === user && status === 'REJECTED') {
$('#termCar').css('display', 'block');
}
});
Here is the HTML:
<div ng-repeat="car in myCars['My CARs']" class="myCar">
<div class="carId">{{ car['Display Name'] }}</div>
<div class="title">{{ car['Project Title'] }}</div>
<div id="termCar" class="termCar"><a ui-sref="taskDetails">Terminate</a></div>
</div>
I know that it has something to do with these lines (obviously):
originator = $scope.myCars["My CARs"]["Current Approver"],
status = $scope.myCars["My CARs"].Status
I just cant figure out how to pull specific data out of an array i guess.
I need to be able to loop through the array of objects and find the ones that meet that if statement and then if one of those does then run the jQuery line.
Thanks for any help.

Try:
originator = $scope.myCars["My CARs"][0]["Current Approver"];
status = $scope.myCars["My CARs"][0].Status
You're simply not referencing which index in the array you wish to grab the values from.

You're right, the issue is this:
$scope.myCars["My CARs"]["Current Approver"]
For that to work, your data structure would have to look like this:
"My CARS": {
"Current Approver": "..."
}
My CARs is an array of objects, so you need to iterate over that array. You would typically do this with a basic forEach. Lodash makes this nice to do, but I'll use native js:
var user = localStorage.getItem('user');
$http.get('/car').success(function(data) {
var cars = data['My CARs'];
cars.forEach(function(car) {
if (car["Current Approver"] === user && car.Status === 'REJECTED') {
// do stuff
}
});
});

you need to filter the array My CARs to match the local user
$http.get(API + '/car').success(function(data) {
$scope.myCars = data;
console.log(data);
var user = localStorage.getItem('user') || null;
var originator = $scope.myCars["My CARs"].filter(function(d) {
return d["Current Approver"] === user && d["Status"] === 'REJECTED'
});
if (originator.length) {
$('#termCar').css('display', 'block');
}
});

Try this:
var cars = $scope.myCars["My CARs"];
for(int i = 0; i < cars.length; i++) {
var theCar = cars[i];
if(theCar["Current Approver"] === user && theCar["Status"] === "REJECTED") {
originator = theCar["Current Approver"];
status = theCar.Status;
break;
}
}
This will give you the status of the first car that matches whose Current Approver matches the user.

Related

Matching a variable with an object inside a nested array with JavaScript

I am trying to find a match inside this JSON array but I find it a bit complicated since it's a nested array of objects.
I'm not sure what I am doing entire wrong here:
The idea is that I have an array with a set of permissions and I want to return only the set of permissions that match the role:
var data = [{
"visitor": {
"static": ["page-one:visit", "home-page:visit", "login"]
}
}, {
"users": {
"static": ["posts:list", "posts:create", "users:getSelf", "home-page:visit", "dashboard-page:visit"]
}
}, {
"admin": {
"static": ["posts:list", "posts:create", "posts:edit", "posts:delete", "users:get", "users:getSelf", "home-page:visit", "dashboard-page:visit"]
}
}]
var role = "admin"
for(var x=0;x <data.length;x++){
if(role === data[x]){
console.log("OLE, we got a match!" + data[x])
}
}
For some reason I just can't find a match. I just wanna return the full object like:
"admin":{
"static": ["posts:list", "posts:create", "posts:edit", "posts:delete", "users:get", "users:getSelf", "home-page:visit", "dashboard-page:visit"]
}
Here is a JS Bin Link.
You could use the .find function like below:
data.find(function(x){ return Object.keys(x).indexOf(role) > -1; });
Given your role is the key of the object, you need to check if the object itself contains the role as a key, for this you'd use Object.keys(<object>).indexOf(role) where indexOf will return the value of -1 if it's not found and 0+ if found.
var data = [{"visitor":{"static":["page-one:visit","home-page:visit","login"]}},{"users":{"static":["posts:list","posts:create","users:getSelf","home-page:visit","dashboard-page:visit"]}},{"admin":{"static":["posts:list","posts:create","posts:edit","posts:delete","users:get","users:getSelf","home-page:visit","dashboard-page:visit"]}}]
var role = "admin"
var admins = data.find(function(x){ return Object.keys(x).indexOf(role) > -1; });
console.log(admins);
if you wanted to accommodate for an array of different roles, you can use the following, easy to follow example.
var data = [{"visitor":{"static":["page-one:visit","home-page:visit","login"]}},{"users":{"static":["posts:list","posts:create","users:getSelf","home-page:visit","dashboard-page:visit"]}},{"admin":{"static":["posts:list","posts:create","posts:edit","posts:delete","users:get","users:getSelf","home-page:visit","dashboard-page:visit"]}}]
var role = ["admin", "visitor"];
var admins = role.map(function(role) { return getObjectsForRole(role); })
function getObjectsForRole(role)
{
return data.find(function(x){
return Object.keys(x).indexOf(role) > -1;
});
}
console.log(admins);
The above is pretty much the same as before, but we're mapping (.map) each role and calling a function which contains our call to the .find function.

How to get specific data in JSON result

Here my JSON result of my "modeles" of car:
[
{
"idModele":1,
"modele":"M3",
"marque":{
"idMarque":1,
"marque":"BMW"
}
},
{
"idModele":2,
"modele":"RS6",
"marque":{
"idMarque":2,
"marque":"Audi"
}
},
{
"idModele":3,
"modele":"C63 AMG",
"marque":{
"idMarque":3,
"marque":"Mercedes"
}
},
{
"idModele":4,
"modele":"Clio RS Trophy",
"marque":{
"idMarque":4,
"marque":"Renault"
}
},
{
"idModele":5,
"modele":"Scirocco Type R",
"marque":{
"idMarque":5,
"marque":"Volkswagen"
}
},
{
"idModele":6,
"modele":"118d",
"marque":{
"idMarque":1,
"marque":"BMW"
}
}
]
I just want to get the "modeles" that have the "idMarque:1" (BMW) (in my result they have 2 "modeles") but I don't know how to do it.
My backend : API REST with SpringBoot
My frontend : Angular
Assuming the json array is stored in the variable result, you may simply:
Loop over the json-array.
Check each json-object for the desired condition.
for (let i = 0; i < result.length; i++) {
if (result[i].marque.idMarque === 1) {
console.log('Found it ', result[i]);
}
}
Even simpler:
result.filter(e => e.marque.idMarque === 1);
First, just for clarification, this is a javascript question. It doesn't matter what your backend or frontend is.
Answering your question, you can filter your result to get only the elements you're seeking:
filteredCars = cars.filter(car => car.marque.idMarque === 1)
This will filter the cars with marque.idMarque = 1.
You can find about the filter function on the docs.
You can get the model having idMarque:1 using filter operator. For example you get the JSON result in result class variable. Then you can use filter as follows.
let BMWCars = this.result.filter(e => e.marque.idMarque == 1);
Is a good idea to check, if you have searched object values, so:
let filtered = models
.filter(item => item.marque && item.marque.idMarque
? item.marque.idMarque === 1
: '')
In this case, if you did not get error, when marque key is missing from server response.

How to change value of Object inside an Array?

I want to change the values of the objects inside an array. I have created an object which I insert in every loop in an array.
If encountered with a missing value, I want to update the values of the existing object.
When the loop runs, it always enters the last object details from the api into the array.
Here; the screenshot: https://i.imgur.com/8uqOIaZ.png
var msg = data.message; // messages array from api
let body;
let posts = [];// empty array created
//object structure
let post ={
id:'',
desc: '',
creator: '',
time: '',
likes: 0,
attachment: '',
};
for(let i in msg){
if(msg[i].body.includes(':')){ //if message body include object notation ':'
body = JSON.parse(msg[i].body); // parse text message body into json
if(body.contentDescription){ //if content is true
post.id = body.postId; //id
post.creator = body.createdUserName; //post creator
post.time = body.publishedDate; //post publish date
post.desc = body.contentDescription; //post content
posts.push(post);
}
else if(posts.length > 1){
for(let j in posts){
if(posts[j].id === body.postId){
console.log(posts[j].id);
if(body.likeCount){ //if likeCount is true
posts[j].likes += 1; //increase like count
}else if(body.attachmentId){ //of Attachment is true
posts[j].attachment = body.attachmentId; // update attachement value
}
}
break;
}
}
}
};
Please help where am I doing it wrong?
Objects in JavaScript are sent via a link to the piece of memory. So when you change your post you are changing all the posts because all of them are looking to the same piece of memory.
You can change your code in a next way so it start working correct
...
if(body.contentDescription){ //if content is true
let postItem = Object.assign({}, post); // Coping an object so breaking the memory link
postItem.id = body.postId; //id
postItem.creator = body.createdUserName; //post creator
postItem.time = body.publishedDate; //post publish date
postItem.desc = body.contentDescription; //post content
posts.push(postItem);
}
...
However, there is more than one way to skin a cat so this is not the only solution.

Improve loop over nested properties - javascript

Trying to filter students according to a nested property value.
Basically each student object has property of type array : studentSuperSubject
which in turn has array as a property as well : studentSubSubjectOrSkill
subjects is array of objects in the following form:
{superSubject: "some super subject name", subSubject: "some sub subject name"}.
each subSubject inside studentSubSubjectOrSkill has the property studentSubSubjectScore which is the one I'm looking for.
I want to loop over the students array for each subject in subjects and create and object i then store to another array - grades=[]
I manage to get it done with what looks like a Hugh bawl of spaghetti code:
for (let subject of subjects) {
var grades = [];
this.data.students.filter(student => {
let name = student.studentName;
// loop over each student > superSubject > subSubject
for (let superSubject of student.studentSuperSubject) {
if (superSubject.superSubjectName === subject.superSubject) {
superSubject.studentSubSubjectOrSkill.filter(sub => {
if (sub.subSubjectName === subject.subSubject) {
grades.push({
name: name,
pass: sub.studentSubSubjectScore > 58
});
return;
}
});
}
}
});
subject["grades"] = grades;
}
Any idea how can I improve that to make life easier for the future developers which are going to use this code?
as a side note, lodash is available in this project
thanks.
1/ You have improper use of filter that should be used when you want to return subset of the array, you should use map when you want to execute an action for each element of the array
2/ for... of ... is for iterating over the values, for... in... over the properties
3/ I think it is more readable like this:
for (let subject of subjects) {
var grades = [];
this.data.students.map(student => {
let name = student.studentName;
student.studentSuperSubject
.filter(superSubject => superSubject.superSubjectName === subject.superSubject)
.map(superSubject=> {
superSubject.studentSubSubjectOrSkill
.filter(sub => sub.subSubjectName === subject.subSubject)
.map(sub=>{
grades.push({
name: name,
pass: sub.studentSubSubjectScore > 58
});
});
});
});
subject["grades"] = grades;
}
For readability, I would check one thing at a time and add some comments.
// Iterates for all subjects.
subjects.forEach(subject => {
// Subject grades.
subject.grades = [];
// Iterates for all the students.
students.forEach(student => {
// Finds and validates the student super subject.
var studentSuperSubject = student.studentSuperSubject.find(superSubject => superSubject.superSubjectName === subject.superSubject);
if (!studentSuperSubject) return;
// Finds and validates the student sub subject.
var studentSubSubject = studentSuperSubject.studentSubSubjectOrSkill.find(subSubject => subSubject.subSubjectName == subject.subSubject);
if (!studentSubSubject) return;
// Saves the student grade.
subject.grades.push({
name: student.studentName,
pass: studentSubSubject.studentSubSubjectScore > 58
});
});
});

Adding an Object to an Array

I'm struggling on adding an Object to an Array (E-commerce context).
My "tc_vars" datalayer is mapped with another datalayer which is called "wa_data". The latter sends the requested information to the first one.
An Object in that case will be a specific product and the Array will be the cart.content property :
var tc_vars = {
nav : {
siteCategory : wa_data.nav.siteCategory,
environment :wa_data.nav.environment,
siteType :wa_data.nav.siteType,
siteName :wa_data.nav.siteName,
pageName :wa_data.nav.pageName,
siteSection :wa_data.nav.siteSection,
country :wa_data.nav.country,
language :wa_data.nav.language,
template :wa_data.nav.template,
doNotTrack :window.navigator.doNotTrack,
customReferrer :wa_data.nav.customReferrer,
genomeID :wa_data.nav.genomeID,
mdmBID :wa_data.nav.mdmBID,
mdmIID :wa_data.nav.mdmIID
},
profile : {
uplayID : readCookie("user_id"),
loginStatus : ''
},
internalSearch : {
searchStatus :wa_data.internalSearch.searchStatus,
searchFilters :wa_data.internalSearch.searchFilters,
searchKeyWord :wa_data.internalSearch.searchKeyWord,
totalResults :wa_data.internalSearch.totalResults,
resultPosition :wa_data.internalSearch.resultPosition,
autoCompletion :wa_data.internalSearch.autoCompletion
},
product : {
productID :wa_data.product.productID,
unitSalePrice :wa_data.product.unitSalePrice,
salePrice :wa_data.product.salePrice,
stockAvailability :wa_data.product.stockAvailability,
salesType :wa_data.product.salesType,
costOfGood :wa_data.product.costOfGood
},
cart : {
orderID:wa_data.cart.orderID,
cartOpen:wa_data.cart.cartOpen,
cartAdd:wa_data.cart.cartAdd,
cartRemove:wa_data.cart.cartRemove,
cartView:wa_data.cart.cartView,
checkout:wa_data.cart.checkout,
purchase:wa_data.cart.purchase,
currency:wa_data.cart.currency,
paymentMethod:wa_data.cart.paymentMethod,
orderShipping:wa_data.cart.orderShipping,
orderTotalAmountDiscounted:wa_data.cart.orderTotalAmountDiscounted,
orderTotalAmountNotDiscounted:wa_data.cart.orderTotalAmountNotDiscounted,
orderTaxAmount:wa_data.cart.orderTaxAmount,
orderDiscountedAmount:wa_data.cart.orderDiscountedAmount,
orderShippingCost:wa_data.cart.orderShippingCost,
billingRegion:wa_data.cart.billingRegion,
billingCity:wa_data.cart.billingCity,
orderStatus:wa_data.cart.orderStatus,
content : [{
productID:'',
name:'',
quantity :'',
promoCode:'',
offerID:'',
salesType:'',
platform :'',
unitSalePrice:'',
salePrice:'',
stockAvailability:'',
lineItemTotalAmountDiscounted:'',
lineItemTotalAmountNotDiscounted:'',
lineItemTaxAmount:'',
lineItemDiscountedAmount:'',
lineItemShippingCost:'',
crossSell:'',
upSell:''
}]
},
tech : {
containerVersion : wa_data.tech.containerVersion
}
}
//Scanning for the content using a loop
if (typeof tc_vars.cart.content !== 'undefined' && tc_vars.nav.pageName === 'Basket'){
for(i=0; i < tc_vars.cart.content.length; i++) {
tc_vars.cart.content[i].productID = wa_data.cart.content[i].productID;
tc_vars.cart.content[i].name = wa_data.cart.content[i].name;
tc_vars.cart.content[i].quantity = wa_data.cart.content[i].quantity;
tc_vars.cart.content[i].promoCode = wa_data.cart.content[i].promoCode;
tc_vars.cart.content[i].offerID = wa_data.cart.content[i].offerID;
tc_vars.cart.content[i].salesType = wa_data.cart.content[i].salesType;
tc_vars.cart.content[i].platform = wa_data.cart.content[i].platform;
tc_vars.cart.content[i].unitSalePrice = wa_data.cart.content[i].unitSalePrice;
tc_vars.cart.content[i].salePrice = wa_data.cart.content[i].salePrice;
tc_vars.cart.content[i].stockAvailability = wa_data.cart.content[i].stockAvailability;
tc_vars.cart.content[i].lineItemTotalAmountDiscounted = wa_data.cart.content[i].lineItemTotalAmountDiscounted;
tc_vars.cart.content[i].lineItemTotalAmountNotDiscounted = wa_data.cart.content[i].lineItemTotalAmountNotDiscounted;
tc_vars.cart.content[i].lineItemTaxAmount = wa_data.cart.content[i].lineItemTaxAmount;
tc_vars.cart.content[i].lineItemDiscountedAmount = wa_data.cart.content[i].lineItemDiscountedAmount;
tc_vars.cart.content[i].lineItemShippingCost = wa_data.cart.content[i].lineItemShippingCost;
tc_vars.cart.content[i].crossSell = wa_data.cart.content[i].crossSell;
tc_vars.cart.content[i].upSell = wa_data.cart.content[i].upSell;
}
}
The problem I'm facing here is that my code is not creating a new object for each new product that is added to the cart content (with all the dedicated properties of the new object).
I've tried using a loop which scans my cart content Array but apparently it's not working (not adding a new object inside the Array). Seems like I'm missing something.
Do you guys have any ideas?
Thx a lot
J
tc_vars.cart.content[i] is undefined. You need to define it first, before filling it up.
for(i=0; i < tc_vars.cart.content.length; i++) {
tc_vars.cart.content[i] = {}; // Creates an empty object
tc_vars.cart.content[i].productID = wa_data.cart.content[i].productID; // Starts filling it
// ....
}
As an alternative (lighter syntax and faster execution), you could also write :
for(i=0; i < tc_vars.cart.content.length; i++) {
tc_vars.cart.content[i] = {
productID : wa_data.cart.content[i].productID,
name : wa_data.cart.content[i].name,
// ....
}
}
But we don't usually add things to an Array by its index. We just push things into it :
for(i=0; i < tc_vars.cart.content.length; i++) {
tc_vars.cart.content.push({
productID : wa_data.cart.content[i].productID,
name : wa_data.cart.content[i].name,
// ....
});
}
This being said, it looks like all you're doing here is copying (not instanciating) wa_data.cart.content into tc_vars.cart.content. So you can completely forget my answer and replace your whole for loop with Gurvinder's answer (+1'd him):
tc_vars.cart.content = JSON.parse(JSON.stringify(wa_data.cart.content));
Unless wa_data already have objects repeated at all the index, following code should work
tc_vars.cart.content = JSON.parse(JSON.stringify(wa_data.cart.content));
You can use an object literal:
tc_vars.cart.content[i] = {
productID: wa_data.cart.content[i].productID,
name: wa_data.cart.content[i].name,
quantity: wa_data.cart.content[i].quantity,
promoCode: wa_data.cart.content[i].promoCode,
offerID: wa_data.cart.content[i].offerID,
salesType: wa_data.cart.content[i].salesType,
platform: wa_data.cart.content[i].platform,
unitSalePrice: wa_data.cart.content[i].unitSalePrice,
salePrice: wa_data.cart.content[i].salePrice,
stockAvailability: wa_data.cart.content[i].stockAvailability,
lineItemTotalAmountDiscounted: wa_data.cart.content[i].lineItemTotalAmountDiscounted,
lineItemTotalAmountNotDiscounted: wa_data.cart.content[i].lineItemTotalAmountNotDiscounted,
lineItemTaxAmount: wa_data.cart.content[i].lineItemTaxAmount,
lineItemDiscountedAmount: wa_data.cart.content[i].lineItemDiscountedAmount,
lineItemShippingCost: wa_data.cart.content[i].lineItemShippingCost,
crossSell: wa_data.cart.content[i].crossSell,
upSell: wa_data.cart.content[i].upSell
}

Categories