Constructing multidimensional array out of other arrays - javascript

I’m using an external service to pull the events of an organisation (GetEvents). Example of what is returned:
{
"Result":"success",
"Key":"12345",
"Data":[
{"ID":"GFDCV34","lastChangedDate":"2015-12-03 11:14:27"},
{"ID":"IDJHE23","lastChangedDate":"2015-12-03 15:17:47"},
{"ID":"KDJBD34","lastChangedDate":"2015-12-03 05:25:11"}
]
}
Next, I can pull details of a certain event (GetEventDetails). The ID of the event is required as data parameter. I made a function getdetails(id); that returns the details.
For example, for getdetails('KDJBD34'), it gives me:
{
"Result":"success",
"Key":"52523",
"Data":[
{
"ID": "KDJBD34",
"name": "Name of event 3",
"date": "date of event 3",
"location": "location of event 3",
"lastChangedDate":"2015-12-03 05:25:11"
}
]
}
I want to construct an array containing all the events and their details, like this:
{
"Result": "success",
"Key": "12345",
"Data":[
{
"ID": "GFDCV34",
"name": "Name of event 1",
"date": "date of event 1",
"location": "location of event 1",
"lastChangedDate": "2015-12-03 11:14:27"
},
{
"ID": "IDJHE23",
"name": "Name of event 2",
"date": "date of event 2",
"location": "location of event 2",
"lastChangedDate": "2015-12-03 15:17:47"
},
{
"ID": "KDJBD34",
"name": "Name of event 3",
"date": "date of event 3",
"location": "location of event 3",
"lastChangedDate":"2015-12-03 05:25:11"
}
]
}
Anyone who can point me in the right direction?

You should operate through your first results and attach the new retrieved properties
var res = {
"Result": "success",
"Key": "12345",
"Data": [{
"ID": "GFDCV34",
"lastChangedDate": "2015-12-03 11:14:27"
}, {
"ID": "IDJHE23",
"lastChangedDate": "2015-12-03 15:17:47"
}, {
"ID": "KDJBD34",
"lastChangedDate": "2015-12-03 05:25:11"
}]
};
var tmp;
res.Data.map(function(val,i){
tmp = getdetails(val.ID);
Object.keys(tmp.Data[0]).map(function(v,j){
val[v] = tmp.Data[0][v];
});
});
Demo

Related

Group by property of an object within a nested array

How would you group an array by a property of the objects in a nested array. Either vanilla or lodash.
For example, how would you group an array of tasks by the assignee, when tasks can have more than one person assigned.
Example data:
[
{
"assignees": [
{
"name": "John",
"uid": "id0001"
},
{
"name": "Sally",
"uid": "id0002"
}
],
"title": "Task 1",
"status": "To do"
},
{
"assignees": [
{
"name": "John",
"uid": "id0001"
}
],
"title": "Task 2",
"status": "To do"
},
{
"assignees": [
{
"name": "Sally",
"uid": "id0002"
}
],
"title": "Task 3",
"status": "To do"
}
]
Example desired result:
{
"id0001": {
"name": "John",
"tasks": [
{
"title": "Task 1",
"status": "To do"
},
{
"title": "Task 2",
"status": "To do"
}
]
}
},
{
"id0002": {
"name": "Sally",
"tasks": [
{
"title": "Task 1",
"status": "To do"
},
{
"title": "Task 3",
"status": "To do"
}
]
}
}
I have a lot of things both vanilla and lodash - a simple example is below. I was expecting an array of three groups. One for Sally, one for John and one for Sally and John:
const grouped = _.groupBy(taskList, (task) => task.assignees);
But that returns one group [object Object] with all the tasks in it.
Since uids are unique, the Array seems like an overhead.
I suggest to get an Object literal with the tasks grouped by the user's uids: like:
{
id0001: {...user, tasks: []},
id0002: {...user, tasks: []},
}
Example:
const groupTasksByUserId = (arr) => arr.reduce((ob, {assignees, ...task}) => {
assignees?.forEach((user) => {
ob[user.uid] ??= {...user, tasks: []};
ob[user.uid].tasks.push(task)
});
return ob;
}, {});
const data = [{
"assignees": [{"name": "John", "uid": "id0001"}, {"name": "Sally","uid": "id0002"}],
"title": "Task 1",
"status": "To do"
}, {
"assignees": [{"name": "John", "uid": "id0001"}],
"title": "Task 2",
"status": "To do"
}, {
"assignees": [{"name": "Sally", "uid": "id0002"}],
"title": "Task 3",
"status": "To do"
}];
const res = groupTasksByUserId(data);
// console.log(res);
console.log(JSON.stringify(res, 0, 2));
Find out more about the above used Array methods (reduce and forEach) on MDN Docs

Find by key and replace the value in an object

I'm a bit new with javascript. Is there a way to find all icon and get their value and then replace their values with a new one?
I need to replace all of fa/FaCopy with fcb/FcbCopy in the json payload below. Any libraries or functions you can share?
[
{
"section": "feature-list",
"data": {
"title": "Title here",
"body": "body here",
"features": [
{
"title": "Title here 1",
"image": "body here",
"icon": "fa/FaCopy"
},
{
"title": "Title here 2",
"image": "body here",
"icon": "fa/FaCopy"
},
{
"title": "Title here 3",
"image": "body here",
"icon": "fa/FaCopy"
}
]
}
},
{
"section": "title-list",
"data": {
"title": "Title here",
"titles": {
"list": [
{
"title": "Title here 1",
"icon": "fa/FaCopy"
},
{
"title": "Title here 2",
"icon": "fa/FaCopy"
},
{
"title": "Title here 3",
"icon": "fa/FaCopy"
}
]
}
}
}
]
This will be very customized solution and deeply depended on your data.
If your data type will not change and remain same then you could use/modify something like this.
// DATA = Your array
const result = DATA.map((list) => ({
...list,
data: {
...list.data,
features: list.data.features?.map((feature) => ({
...feature,
icon: feature.icon === 'fa/FaCopy' ? 'fcb/FcbCopy' : feature.icon
})),
},
}));
console.log(result); // your expected result

Remove item from nested array object in Javascript by key value

I have object like this:
{
"id": 1,
"name": "first",
"sections": [
{
"id": 1,
"title": "First section",
"contents": [
{
"id": "123",
"title": "Sample title 1",
"description": "<html>code</html>",
},
{
"id": "124",
"title": "Sample title 2",
"description": "<html>code</html>"
},
{
"id": "125",
"title": "Some other sample",
"description": "<html>code</html>"
}
]
},
{
"id": 2,
"title": "Second section",
"contents": [
{
"id": "126",
"title": "Sample title 126",
"description": "<html>code</html>"
},
{
"id": "127",
"title": "Sample title 127",
"description": "<html>code</html>"
}
]
}
]
}
I want to remove specific object from contents array by its id (all those ids are unique).
I can easily find element I want to remove, but I'm unable to find in which section this element is to splice it later.
obj.sections.forEach(function(section) {
section.contents.forEach((content) => {
if (content.id == 125) {
console.log(content)
console.log(section)
}
})
})
In above code console.log(sections) returns undefined. How can I get position in sections array which contains contents array that has specific id. For example, id: 125 would return sections position 0, so I can use splice to remove that element.
If my approach is completely wrong please point me in right direction, thanks :)
You could use .filter() instead of .splice(). .filter() will keep all items which you return true for and discard of those which you return false for. So, if the current section's content's object has an id equal to the one you want to remove you can return false to remove it, otherwise return true to keep that item. You can use this with .map() to map each section object to a new one with an updated contents array:
const obj = { "id": 1, "name": "first", "sections": [ { "id": 1, "title": "First section", "contents": [ { "id": "123", "title": "Sample title 1", "description": "<html>code</html>", }, { "id": "124", "title": "Sample title 2", "description": "<html>code</html>" }, { "id": "125", "title": "Some other sample", "description": "<html>code</html>" } ] }, { "id": 2, "title": "Second section", "contents": [ { "id": "126", "title": "Sample title 126", "description": "<html>code</html>" }, { "id": "127", "title": "Sample title 127", "description": "<html>code</html>" } ] } ] };
const idToRemove = 125;
obj.sections = obj.sections.map(
sec => ({...sec, contents: sec.contents.filter(({id}) => id != idToRemove)})
);
console.log(obj);
.as-console-wrapper { max-height: 100% !important; top: 0; } /* ignore */
Why not use a simple filter for accomplishing the task. Also, it will be much cleaner and immutable way of doing it.
let newArrWithoutContentWithGivenId = obj.sections.map(section =>
({...section, contents: section.contents.filter(content =>
content.id != 125)}));
Here, we are mapping each section whose content does not contain the ID 125. In short, section > content.id != 125 will be removed from the new array.
Hope it helps :)
Note: Code is not tested, it is just to help you find a way to do it cleanly.
You only need to use the second argument of forEach :)
obj.sections.forEach(function(section, sectionIndex) {
section.contents.forEach((content, contentIndex) => {
if (content.id == 125) {
// use the sectionIndex and contentIndex to remove
}
})
})

FullCalendar doesn't display events fetched via JSON with Dynamic 'extraParams' parameter

I'm having problems dislaying events fetched via JSON with Dynamic 'extraParams' parameter as explained here in the Docs:
var calendarEl = document.getElementById('calendar');
calendar = new FullCalendar.Calendar(calendarEl, {
...,
events: {
url: '/getEvents',
method: 'POST',
extraParams: function() {
var combobox = document.getElementById('combobox');
var value = combobox.options[combobox.selectedIndex].value;
return {client: value};
},
failure: function(error) {
console.log(error);
alert("Error", "Unable to fetch events", "red");
},
},
...
});
calendar.render();
On the debug panel, I can see the request made by FullCalendar:
XHR POST https://127.0.0.1:8443/getEvents
With this params:
client: All
start: 2019-09-30T00:00:00Z
end: 2019-11-11T00:00:00Z
timeZone: UTC
And the response:
{
"error": "",
"events": [
{
"allDay": 1,
"color": "blue",
"end": "2019-10-24T00:00:00.000Z",
"extendedProps": {
"company": "Company 1",
"state": "Active",
"type": "task"
},
"groupId": "48",
"id": 27,
"start": "2019-10-23T00:00:00.000Z",
"title": "Title 1",
"url": ""
},
{
"allDay": 1,
"color": "blue",
"end": "2019-11-07T00:00:00.000Z",
"endpoints": 0,
"extendedProps": {
"company": "All",
"description": "Description",
"creationDate": "2019-11-04",
"state": "Active",
"tecnology": "test",
"element": "test 1",
"type": "type 2",
"user": "user 1",
"version": "1.2"
},
"id": 76,
"start": "2019-11-04T00:00:00.000Z",
"title": "Title 2",
"url": ""
}
]
}
But FullCalendar doesn't display this two received events. I don't know what I'm doing wrong.
Regards.
This is happening because your server must return a simple array containing only the events, and nothing else. You're returning a complex object. FullCalendar does not know how to unpack your object and find the "events" property containing the relevant data.
You need to return simply:
[
{
"allDay": 1,
"color": "blue",
"end": "2019-10-24T00:00:00.000Z",
"extendedProps": {
"company": "Company 1",
"state": "Active",
"type": "task"
},
"groupId": "48",
"id": 27,
"start": "2019-10-23T00:00:00.000Z",
"title": "Title 1",
"url": ""
},
{
"allDay": 1,
"color": "blue",
"end": "2019-11-07T00:00:00.000Z",
"endpoints": 0,
"extendedProps": {
"company": "All",
"description": "Description",
"creationDate": "2019-11-04",
"state": "Active",
"tecnology": "test",
"element": "test 1",
"type": "type 2",
"user": "user 1",
"version": "1.2"
},
"id": 76,
"start": "2019-11-04T00:00:00.000Z",
"title": "Title 2",
"url": ""
}
]
from your server, without the rest of it.
I must say that the fullCalendar documentation doesn't make this fact particularly clear.
N.B. I'd argue the "errors" property is superfluous anyway, in any JSON response. If there was an error, you should return a HTTP status code indicating the nature of the error, and a completely different response body indicating whatever you want to tell the user about the error. This would fire the "failure" callback in your JS and allow the browser code to respond appropriately.

Filtering JSON with underscore

Given a data structure like so:
"items":
{
"Groups":[
{
"title":"group 1",
"SubGroups":[
{
"title":"sub1",
"id" : "1",
"items":[
{
"title":"Ajax request 1",
},
{
"title":"Ajax request 2",
}
]
},
{
"title":"sub2",
"id" : "2",
"items":[
{
"title":"Ajax request 3",
},
{
"title":"Ajax request 4",
}
]
}
]
}
]
How can I pull out all the items for a sub group based on the id? Ive treid using find like so:
var res1 = _.where(listing.items,{id:"2"});
but get an empty array returned
Thanks
Try targeting the subgroups array and then search for the id you want in there. That should then return the properties for that subgroup.
var obj = {
"Groups": [{
"title": "group 1",
"SubGroups": [{
"title": "sub1",
"id": "1",
"items": [{
"title": "Ajax request 1",
}, {
"title": "Ajax request 2",
}]
}, {
"title": "sub2",
"id": "2",
"items": [{
"title": "Ajax request 3",
}, {
"title": "Ajax request 4",
}]
}]
}]
}
then find values like this
_.where(obj.Groups[0].SubGroups, {
'id': '2'
});
Just tested and this seems to work

Categories