Displaying data inside an array inside an object with React - javascript

I have some data in a separate JS file called data.js
export default [
{
info: [
{
cardOne: [
{
division: "Company Division",
infotext: "Some Text",
cta: "Story Information",
},
],
},
{
cardTwo: [
{
division: "Rec Division",
infotext: "Some Text",
cta: "Story Information",
},
],
},
{
cardThree: [
{
division: "Professional Division",
infotext: "Some Text",
cta: "Story Information",
},
],
},
],
},
]
In a component I want to display the division of cardOne.
Is there a way to access and display just the division of CardOne and display that?

Yes, you can by calling .map on just the cardOne array in your data.
const data = 'location of your exported data';
data['info'][0]['cardOne'].map((card) => (
JSX here
))

If you just want the division of cardOne you can access it like this:
import * as data from "./data"
<h1>{data.default[0].info[0].cardOne[0].division}</h1>

Related

How to add object in Array of Objects using Node js in Mongodb?

I want to update my courseModules inside MasterCourse. In below JSON I have two Objects in courseModules. I want if moduleId exist in courseModules then update it else create a new object and return the courseModules with updated value.
I am using Node js and mondodb, mongoose. Not able to find how can I achieve this functionality.
JSON OR MONGODB Data:
"MasterCourse": [
{
"_id": "6392f2611e7d670eca9712fa",
"courseTitle": "My Course Title",
"awardURL": "award.png",
"courseModules": [
{
"moduleId": 0,
"moduleTitle": "Module Title 1",
"moduleDescription": "Module 1 description",
"totalSessions": 3,
"_id": "6392f2611e7d670eca97e12d"
},
{
"moduleId": 1,
"moduleTitle": "ModuleTitle 2",
"moduleDescription": "Module 2 description",
"totalSessions": 4,
"_id": "6392f2611e7d670eca9711wd"
},
],
}
]
Query want to perform:
{
"moduleId": 2,
"moduleTitle": "Module Title 3",
"moduleDescription": "Module 3 description",
"totalSessions": 8,
}
To add if item not exist -
masterCourse.updateOne({ "_id": req.params.id }, { $addToSet: { "courseModules": req.body } })
To update the value if exist -
masterCourse.updateOne({ "_id": req.params.id, "courseModules._id": ModuleID }, { $set: { "courseModules": req.body } })
These queries works for me, you can change the variable's name according to your data or requirement.

Why ng2-tree is showing undefined

I'm using ng2-tree https://angular2-tree.readme.io/v3.2.0/docs/inputs plugin
When i input below json it is showing as undefined
[
{
"value": "helper",
"name": "helper",
"children": []
},
{
"value": "taxi",
"name": "taxi",
"children": []
},
{
"value": "Cake",
"name": "Cake",
"children": [
{
"name": "Chocolate Fudge Cake",
"value": "Chocolate Fudge Cake"
},
{
"name": "Carrot & Walnut Cake",
"value": "Carrot & Walnut Cake"
}
]
}
]
with above json my result is as undefined you can see them in my provided link below
here is the stackblitz link: https://stackblitz.com/edit/angular-ng2-tree-aouyza?file=app/app.component.ts
Please help me thanks in advance!!
Your data structure is wrong. The tree component received as input param a TreeModel and you're having an array of TreeModels at the moment.
Either you adjust your data structure and use a parent TreeModel to wrap your current ones as its children, like following:
tree: TreeModel = {
value: 'Parent Model',
children: [
{
value: 'helper',
name: 'helper',
children: [],
},
{
value: 'taxi',
name: 'taxi',
children: [],
},
{
value: 'Cake',
name: 'Cake',
children: [
{
name: 'Chocolate Fudge Cake',
value: 'Chocolate Fudge Cake',
},
{
name: 'Carrot & Walnut Cake',
value: 'Carrot & Walnut Cake',
},
],
}
]
};
Or you iterate over the array in the HTML and use multiple tree components. That would look like following:
<tree [tree]="t" *ngFor="let t of tree"></tree>
For more information see the Github page of ng2-tree ;)
Update:
You still need to adjust the data model the way I suggested but you can hide the empty root node. To do so, you need to do following:
HTML
<tree [tree]="tree" [settings]="{ rootIsVisible: false }"></tree>
Due to this setting a class rootless is applied which hides the empyt root node but only if you've added node_modules/ng2-tree/styles.css to your angular.json or you've added a custom implementation for that class.
You can find the settings doc here.

How to properly iterate and parse nested objects in javascript with or without lodash

I'm currently working on a service that returns the following payload:
{
"account1": {
"app1": {
"status": "Online",
"comments": "blah blah",
"events": [
{
"date": "some date",
"generated_by": "some user"
}
]
}
},
"account2": {
"app1": {
"status": "Offline",
"comments": "blah blah bleh",
"events": [
{
"date": "some date",
"generated_by": "some user"
}
]
},
"app2": {
"status": "Online",
"comments": "blah blah",
"events": [
{
"date": "some date",
"generated_by": "some user"
}
]
}
}
}
I'm trying to render a table with the following fields:
-------------------------------
Application | Account | Status
-------------------------------
app1 | account1 | Online
app1 | account2 | Offline
app2 | account2 | Online
Normally this would be easy to do if my payload would be something like a list of objects but I'm kinda stuck here.
I tried to normalize this payload by extracting each of the fields and creating a new payload by doing something like the following:
const extractAccountNumber = Object.values(payload).map(account => ({account: account}))
which would return:
[
{
"account": "account1"
},
{
"account": "account2"
}
]
I wanted to move on to app name the same way and once I get all my fields I would merge the payload. This has proven to be super cumbersome and I'm sure there is a better, more efficient way to achieve this which I'm probably missing. Any feedback would help me a ton to understand how this can be achieved using javascript with or without lodash.
Iterating by first level and then by second level:
table = [];
for (accountName in apiResponse) {
account = apiResponse[accountName];
for (appName in account) {
app = account[appName];
table.push({
application: appName,
account: accountName,
status: app.status,
});
}
}
Then table is something like this:
[
{
"application": "app1",
"account": "account1",
"status": "Online"
},
{
"application": "app1",
"account": "account2",
"status": "Offline"
},
{
"application": "app2",
"account": "account2",
"status": "Online"
}
]
Can try something like
Object.entries(o).map(([accountName, value]) => ({
account: accountName,
apps: Object.entries(value)
.map(([appName, value]) => ({name: appName, ...value }))
}))
Not sure about structure. Where to put app1 from account2 in that table?

MongoDB find in nested array aggregation

I have nested array documents explained below:
countries: [
{
"id": "id of country",
"cities": [
{
"id": "id of city 1",
"areas": [
{
"id": "id of area 1"
},
{
"id": "id of area 2"
},
{
"id": "id of area 3"
},
{
"id": "id of area 4"
}
]
},
{
"id": "id of city 2",
"areas": [
{
"id": "id of area 1"
},
{
"id": "id of area 2"
},
{
"id": "id of area 3"
},
{
"id": "id of area 4"
}
]
}
]
}
]
My target is to add a field using $addFields to indicate if a given id matching area ID or not.
{$addFields: {
isDeliveringToArea: {
$in: [ObjectId('5db5d11cb18a2500129732a5'),'$countries.cities.areas.id']
}
}}
but apparently $in doesn't work with nested arrays.
I want something like the find method works Model.find({'countries.cities.areas.id': 'areaID'}) but to return a boolean value in the aggregation.
Since there are 3 level nested arrays, we can achieve this with $map which is used to run all/modify the objects. First $map used to go through each country object, the second $map used to go each city objects inside each country object
Update 1
Since you need over all filed, you can do it with $anyElementTrue which helps if there is any element true on our condition, it will emit true.
Working Mongo play ground for overall country
[
{
"$addFields": {
isDeliveringToArea: {
$anyElementTrue: {
$map: {
input: "$countries",
in: {
$anyElementTrue: {
$map: {
input: "$$this.cities",
in: {
$in: [
"6",
"$$this.areas.id"
]
}
}
}
}
}
}
}
}
}
]
I keep the old query for your reference.
Working Mongo playground for each country object

Is there a way to de-dupe a javascript array and combine values of the data?

I'm using an ajax request to grab some XML data which I then need to push into a chart in fusioncharts.
The XML data is formatted as [time taken], [work done], [which team done for], [who did it] (see below).
I'm iterating over the XML and then building the array using the code below:
//Time Recorded
if (columnidchecker == 7781) {
timearray.push($j(this).find('displayData').text());
temp1 = $j(this).find('displayData').text();
}
//Type of Activity
if (columnidchecker == 7782) {
activityarray.push($j(this).find('displayData').text());
temp2 = $j(this).find('displayData').text();
}
//Team Done For
if (columnidchecker == 7783) {
subjectarray.push($j(this).find('displayData').text());
temp3 = $j(this).find('displayData').text();
}
//Name
if (columnidchecker == 7777) {
internalclientarray.push($j(this).find('displayData').text());
temp4 = $j(this).find('userDisplayName').text();
}
});
//PUSH INTO A NEW ARRAY WHICH CAN THEN BE SORTED AND DE-DUPED WITH TIME COMBINED AGAINST ACTIVITY / TEAM.
objectarray.push([temp1, temp2, temp3, temp4]);
This builds an array of entries from the XML which basically outputs to something which looks like this:
0: (4) ["1.50", "Ad-hoc queries or calls", "Team 1", "James"]
1: (4) ["2.50", "Ad-hoc queries or calls", "Team 1", "James"]
2: (4) ["1.00", "Advice", "Team 2", "James"]
3: (4) ["3.50", "Meeting (External 3rd Party)", "Team 1", "James"]
4: (4) ["1.20", "Administration", Team 2", "James"]
5: (4) ["5.50", "Advice", "Team 1", "John"]
I'm trying to build a chart in fusioncharts which needs the format as shown below (ignore foot stuffs - it's taken straight from the fusioncharts help pages!).
{
"chart": {
"theme": "fusion",
"caption": "Revenue split by product category",
"subCaption": "For current year",
"xAxisname": "Quarter",
"yAxisName": "Revenues (In USD)",
"showSum": "1",
"numberPrefix": "$"
},
"categories": [
{
"category": [
{
"label": "Q1"
},
{
"label": "Q2"
},
{
"label": "Q3"
},
{
"label": "Q4"
}
]
}
],
"dataset": [
{
"seriesname": "Food Products",
"data": [
{
"value": "11000"
},
{
"value": "15000"
},
{
"value": "13500"
},
{
"value": "15000"
}
]
},
{
"seriesname": "Non-Food Products",
"data": [
{
"value": "11400"
},
{
"value": "14800"
},
{
"value": "8300"
},
{
"value": "11800"
}
]
}
]
}
The problem i'm having is that I cannot work out how to take the array of data with times, activity, team, name and push them into categories.
I think the first step is to create a new array of names which can be pushed into the "Category" data field in fusioncharts.
I then need a way in which to take the times being recorded against each activity and for each team and make sure it's assigned to the right person within the stacked bar chart and combine the amount of time spent. (i.e. "James" spent a total of 4 hours doing "Ad Hoc Queries and Calls" for Team 1 but this is split across two time entries so I need a way in which to combine them into one.)
Any help on this would be massively appreciated.
I can de-dupe the names to create a new array by using the following code:
namesarray.push(temp4);
uniq = [...new Set(namesarray)];
but after that it starts getting pretty complicated.
Maybe this can help you along the way. It's probably not exactly in the form you want it, but it demonstrates how you could break the problem down into smaller parts.
Pseudo-code:
get the unique names.
get the unique "task" names (for lack of a
better word)
for each unique person name:
3.1. get the data rows for that person
3.2 for each of all unique tasks names:
find the person data rows matching the task name
sum the duration of those data rows
const testData = [
[
"1.50",
"Ad-hoc queries or calls",
"Team 1",
"James"
],
[
"2.50",
"Ad-hoc queries or calls",
"Team 1",
"James"
],
[
"1.00",
"Advice",
"Team 2",
"James"
],
[
"3.50",
"Meeting (External 3rd Party)",
"Team 1",
"James"
],
[
"1.20",
"Administration",
"Team 2",
"James"
],
[
"5.50",
"Advice",
"Team 1",
"John"
]
];
const columnIndexByName = {
TASK_DURATION: 0,
TASK_NAME: 1,
FOR_WHICH_TEAM: 2,
PERSON_DOING_TASK: 3
};
const sum = (acc, next) => acc + next;
const uniqueNames = [...new Set(testData.map(row => row[columnIndexByName.PERSON_DOING_TASK])) ];
const uniqueTaskNames = [...new Set(testData.map(row => row[columnIndexByName.TASK_NAME])) ];
let result = {};
uniqueNames.forEach(personName => {
const personDataRows = testData.filter(row => row[columnIndexByName.PERSON_DOING_TASK] === personName);
let taskDurationsByTaskName = {};
uniqueTaskNames.forEach(taskName => {
const taskRows = personDataRows.filter(row => row[columnIndexByName.TASK_NAME] === taskName);
const taskDurations = taskRows.map(row => Number.parseFloat( row[columnIndexByName.TASK_DURATION] ));
const taskTotalDuration = taskDurations.reduce(sum, 0);
taskDurationsByTaskName[taskName] = taskTotalDuration;
})
result[personName] = taskDurationsByTaskName;
})
const renderData = data => document.querySelector("#output").innerHTML = JSON.stringify(data, null, 2);
renderData(result);
<pre id="output"></pre>

Categories

Resources