Related
Here I am working on nodejs typescript API. I am getting the data array of object using map loop. I am getting the "communes" "category" and "location" data from the another API function using issuerId means ID. I am not getting the "communes" "category" and "location". I attached here my code below.
Object.values(premiumValue).map(async(x:any,index:any)=>{
var issuerId = await Object.values(premiumValue)[index].issuer_id
var Communes = await employerDetail.getSingleProfileType(issuerId, 'Communes')
var category = await employerDetail.getSingleProfileType(issuerId, 'company_type')
var location = await employerDetail.getSingleProfileType(issuerId, 'location')
Object.assign(values[issuerId], { Communes }, { category }, { location })
})
return Object.values(values)
I am getting this kind of data only
[
{
"issuer_id": 64,
"company_name": "Gastro Südtirol",
"Total_Job": 2
},
{
"issuer_id": 70,
"company_youtube": "https://www.youtube.com/channel/UCB2bOahchY6Hsc_WXnQ-NCw",
"company_name": "Auto Hofer",
"Total_Job": 2
},
{
"issuer_id": 72,
"company_name": "Assimeran GmbH",
"Total_Job": 2
}
]
I need this kind of data
[
{
"issuer_id": 64,
"company_name": "Gastro Südtirol",
"Total_Job": 2,
"Communes": [],
"category": [],
"location": [
{
"id": 907,
"location": "brixen"
}
]
},
{
"issuer_id": 70,
"company_youtube": "https://www.youtube.com/channel/UCB2bOahchY6Hsc_WXnQ-NCw",
"company_name": "Auto Hofer",
"Total_Job": 2,
"Communes": [],
"category": [],
"location": [
{
"id": 907,
"location": "brixen"
}
]
},
{
"issuer_id": 72,
"company_name": "Assimeran GmbH",
"Total_Job": 2,
"Communes": [],
"category": [],
"location": [
{
"id": 907,
"location": "brixen"
}
]
}
]
But I am getting data without communes, category, and location". Is there any async/await issue here? How I loop the communes, category, and location data using issuerId?
Without knowing the shape of the API data and whatever values is, here's a guess as to how you could use async/await to pull the data in and format it like you're trying to do. I don't see the need for the async map() function; you could instead use a traditional for loop or for...of and wrap everything in an async function:
/***** IGNORE ALL OF THIS, JUST SETUP CODE ****/
const api = [
{
issuer_id: 64,
Communes: [],
company_type: [],
location: [
{
id: 907,
location: "brixen",
},
],
},
{
issuer_id: 70,
Communes: [],
company_type: [],
location: [
{
id: 907,
location: "brixen",
},
],
},
{
issuer_id: 72,
Total_Job: 2,
Communes: [],
company_type: [],
location: [
{
id: 907,
location: "brixen",
},
],
},
];
const values = {
64: {
issuer_id: 64,
company_name: "Gastro Südtirol",
Total_Job: 2,
},
70: {
issuer_id: 70,
company_youtube: "https://www.youtube.com/channel/UCB2bOahchY6Hsc_WXnQ-NCw",
company_name: "Auto Hofer",
Total_Job: 2,
},
72: {
issuer_id: 72,
company_name: "Assimeran GmbH",
Total_Job: 2,
},
};
/*
* Ignore this, it just makes the async stuff actually mimic an API call
*/
function sleep() {
return new Promise((resolve, reject) => {
const time = Math.random() * 500;
setTimeout(() => resolve(time), time);
});
}
const employerDetail = {
getSingleProfileType: async function (issuerId, key) {
await sleep();
return new Promise((resolve, reject) => {
const foundIndex = api.findIndex((el) => el.issuer_id == issuerId);
if (foundIndex === -1) {
reject(`No data in API for issuerId: ${issuerId}`);
} else {
resolve(api[foundIndex][key]);
}
});
},
};
/**** THIS IS WHERE YOU WOULD START USING THINGS ***/
async function getAPIData() {
const apiData = [];
// I'm just looping through the IDs I see in your output
for (const issuerId of [64, 70, 72]) {
const Communes = await employerDetail.getSingleProfileType(issuerId, "Communes");
const category = await employerDetail.getSingleProfileType(issuerId, "company_type");
const location = await employerDetail.getSingleProfileType(issuerId, "location");
apiData.push(Object.assign(values[issuerId], { Communes, category, location }));
}
return apiData;
}
async function main() {
const apiData = await getAPIData();
console.log(JSON.stringify(apiData, null, 2));
}
main();
I have an array of objects, with nested objects:
const data = [{
"operationId": "6357a5bba0de053fb601d573",
"tags": {
"120": {
"title": "ac milan",
"color": "red",
"updated_at": "2022-10-25 08:52:00",
"created_at": "2022-10-25 08:52:00",
"_id": "6357a3b06891976bca0a9215"
},
"121": {
"title": "napoli",
"color": "blue",
"updated_at": "2022-10-25 08:54:12",
"created_at": "2022-10-25 08:54:12",
"_id": "6357a43470761099ce0049e0"
},
}
}, {
"operationId": "6357a5c9a0de053fb601d574",
"tags": {
"118": {
"title": "ac roma",
"color": "red",
"updated_at": "2022-10-25 07:54:19",
"created_at": "2022-10-25 07:54:19",
"_id": "6357962b6891976bca0a920e"
},
"120": {
"title": "ac milan",
"color": "red",
"updated_at": "2022-10-25 08:52:00",
"created_at": "2022-10-25 08:52:00",
"_id": "6357a3b06891976bca0a9215"
},
}
}];
where:
operationId - id of document;
tags - object with binded to document tags.
Based on the information, I need to display a list of tags in the markup. But the same tag can be attached to different documents (as in the example - the "AC Milan" tag is attached to two documents). In this case, the tag must be rendered once. My current iteration of an array of objects does not take this feature into account, and displays everything in a row, but I don’t really understand how to fix it.
function addExistingTagsToModal(arr) {
let existingTagTitle, existingTagColor, existingTagID;
const constructedData = arr.map(item => {
const operationId = item?.operationId;
const innerValues = Object.values(item.tags);
return innerValues.map(subItem => {
existingTagID = subItem._id;
existingTagTitle = subItem.title;
existingTagColor = subItem.color;
let tagObjMarkup = {
tagMarkup: `<li>${existingTagTitle}</li>`
};
let addedTagList = document.querySelector('.list');
addedTagList.insertAdjacentHTML('afterbegin', tagObjMarkup.tagMarkup);
return {
...subItem,
operationId
}
});
});
}
addExistingTagsToModal(data);
Here is a working example (Codepen). To summarize: in the code above, AC Milan should be displayed 1 time. How to do it?
You just need to keep track of the existing titles, so I created an object const tagTitleDict = {}; and checking a key already in it. If found a key in tagTitleDict then no need to insert it again in the list <ul></ul>.
function addExistingTagsToModal(arr) {
let existingTagTitle, existingTagColor, existingTagID;
const tagTitleDict = {};
const constructedData = arr.map((item) => {
const operationId = item?.operationId;
const innerValues = Object.values(item.tags);
return innerValues.map((subItem) => {
existingTagID = subItem._id;
existingTagTitle = subItem.title;
existingTagColor = subItem.color;
if (!(existingTagTitle in tagTitleDict)) {
let tagObjMarkup = {
tagMarkup: `<li>${existingTagTitle}</li>`
};
let addedTagList = document.querySelector(".list");
addedTagList.insertAdjacentHTML("afterbegin", tagObjMarkup.tagMarkup);
tagTitleDict[existingTagTitle] = true;
}
return {
...subItem,
operationId
};
});
});
}
Have adjusted to your codepen
Hope it helps, cheers!
I am trying to get an array of distinct values from the data structure below. I tried using reduce and object keys with no luck. What can I try next?
Data:
var data = [{
"id": 1,
"Technologies": ["SharePoint", "PowerApps"]
},
{
"id": 2,
"Technologies": ["SharePoint", "PowerApps", "SomethingElse"]
},
{
"id": 3,
"Technologies": ["SharePoint"]
},
{
"id": 4,
"Technologies": ["PowerApps"]
},
{
"id": 5,
"Technologies": null
}
]
Finished result should look like:
var distintValues = ["PowerApps", "SharePoint", "SomethingElse", null]
My attempt:
https://codepen.io/bkdigital/pen/MWEoLXv?editors=0012
You could use .flatMap() with a Set. .flatMap allows you to map each object's technology to one resulting array, and the Set allows you to remove the duplicates. With the help of optional chaining ?., you can also keep the null value (so it doesn't throw when accessing Technologies) like so:
const data = [{ "id": 1, "Technologies": ["SharePoint", "PowerApps"] }, { "id": 2, "Technologies": ["SharePoint", "PowerApps", "SomethingElse"] }, { "id": 3, "Technologies": ["SharePoint"] }, { "id": 4, "Technologies": ["PowerApps"] }, { "id": 5, "Technologies": null } ];
const res = [...new Set(data.flatMap(obj => obj?.Technologies))];
console.log(res);
[...new Set(
data
.map(v => Array.isArray(v.Technologies) ? v.Technologies : [v.Technologies])
.reduce((t, v) => [...t, ...v], [])
)];
I tried to solve this through JS. Here is my code:
const data = [{
"id": 1,
"Technologies": ["SharePoint", "PowerApps"]
}, {
"id": 2,
"Technologies": ["SharePoint", "PowerApps", "SomethingElse"]
}, {
"id": 3,
"Technologies": ["SharePoint"]
}, {
"id": 4,
"Technologies": ["PowerApps"]
}, {
"id": 5,
"Technologies": null
}]
const distintValues = [];
for (let element of data) {
if (element.Technologies != null) {
for (let elem of element.Technologies) {
if (!distintValues.includes(elem)) {
distintValues.push(elem);
}
}
}
}
console.log(distintValues);
In your attempt you tried to do it with reduce so here is how I would do it
var data = [{
"id": 1,
"Technologies": ["SharePoint", "PowerApps"]
},
{
"id": 2,
"Technologies": ["SharePoint", "PowerApps", "SomethingElse"]
},
{
"id": 3,
"Technologies": ["SharePoint"]
},
{
"id": 4,
"Technologies": ["PowerApps"]
},
{
"id": 5,
"Technologies": null
}
];
const objAsArray = Object.keys(data) // first we get the keys
.map(key => data[key]) // then we map them to their value
const technologyMap = objAsArray.reduce((acc, data) => {
// if the entry has technologies we set the key in the accumulation object to true
if (data.Technologies) {
data.Technologies.forEach(tech => acc[tech] = true)
}
return acc;
}, {})
// at the very end we get the keys of the accumulation object
const uniqueTechnologies =
Object.keys(
technologyMap
)
For example, what if I need to sum a certain number (in this case, these are ids) that came from the database?
Laravel/api:
[
{ "id": 3, "created_at": null, "updated_at": null, "name": "Name One" },
{ "id": 4, "created_at": null, "updated_at": null, "name": "Name Two" }
]
Component:
<template>
<div class="font-semibold text-4xl text-gray-600">
{{showTotal}}
</div>
import {mapGetters, mapActions} from 'vuex';
export default {
name: "Total",
mounted() {
this.fetchNames();
},
methods: {
...mapActions(["fetchNames"])
},
computed: {
...mapGetters(["getNames"]),
showTotal() {
return this.getNames[0]['id'] + this.getNames[1]['id']
}
},
}
I got errors in the console, but in Vue.js devtools there is showTotal: 7 Vue.js devtools Console errors
store/modules/names.js:
export default {
state: {
names: [],
},
getters: {
getNames: state => state.names,
},
actions: {
async fetchNames({commit}) {
const response = await axios.get('/api/names');
commit('setNames', response.data);
},
},
mutations: {
setNames: (state, names) => state.names = names,
}
}
You would need reduce to iterate over array
const names = [
{ "id": 3, "created_at": null, "updated_at": null, "name": "Name One" },
{ "id": 4, "created_at": null, "updated_at": null, "name": "Name Two" }
]
const total = names.reduce((total, current) => {
return total += current.id;
}, 0)
console.log(total);
So it would be
showTotal() {
return this.getNames.reduce((total, current) => {
return total += current.id;
}, 0)
}
The console error might be appearing due to this.getNames returning empty array the first time the component is rendered and the api hasn't returned the response yet which is why when you try to access the 0 index's id property it throws an error. (Maybe add in some checks to avoid this error)
You could also try a much simpler way of adding ids by using forEach. Code sample below:
showTotal() {
let total = 0;
this.getNames.forEach((item) => total += item.id);
return total;
}
I have modal, inside the modal there is a form when i click the submit button it will do this.
jquery code:
$('#add-new-content-form').on('submit', e => {
e.preventDefault();
//I want to add this block dates to the data
let blockdates = $("#block-dates").val();
let title = $("#card-title").val();
let catalogId = $("#catalog").val();
let categoryId = $("#category").val();
let subcategoryId = $('#subcategory').val();
let why = $("#why").val();
let description = $('#card-description').val();
let cancellationPolicy = $('#cancellation-policy').val();
let displayPrice = $('#display-price').val();
let displayDiscounted = $('#discounted-price').val();
let displayMaxPax = $('#display-maxpax').val();
let data = {
"blockDates":[
{
"description": "national araw ng mga puso day!",
"notAvailableDate": "2019-02-14 10:00:00"
},
{
"description": "chinese new year!",
"notAvailableDate": "2019-02-25 10:00:00"
}
],
"title": title,
"catalogId": catalogId,
"categoryId": categoryId,
"subcategoryId": subcategoryId,
"why": why,
"description": description,
"cancellationPolicy": cancellationPolicy,
"displayPrice": displayPrice,
"displayDiscounted": displayDiscounted,
"displayMaxPax": displayMaxPax
};
let content = ajax("api/unitContents", JSON.stringify(data), "POST");
// window.location.replace("/category");
});
Now, in the postman there is something just like this:
{
"blockDates":[
{
"description": "national araw ng mga puso day!",
"notAvailableDate": "2019-02-14 10:00:00"
},
{
"description": "chinese new year!",
"notAvailableDate": "2019-02-25 10:00:00"
}
],
"location":{
"identifier":"UBZ190asas11",
"name": "abulalas,purok 4",
"address" : "abulalas1 hagonoy bulacan",
"lat" : 12141.00,
"lng" : 123251.00
},
"units": 2,
"title": "sample unit content",
"catalogId": 6,
"categoryId": 22,
"subcategoryId": 13,
"contentOptions": [
{
"name":"bannana boat",
"maxPax":8,
"isAvailableDayTime":[
9,10,11,12,13,15,16,17,18,
33,34,35,36,37,39,38,39,40,
56,57,58,59,60,62,63,64,65,
80,81,82,83,84,86,87,88,89,
104,105,106,107,108,110,111,112,113,
128,129,130,131,132,134,135,136,137,
152,153,154,155,156,158,159,160,161
],
"inventoryNeededSet":[
{
"inventoryId": 1,
"count":1
},
{
"inventoryId": 1,
"count":2
}
],
"paxPrices": [
{
"count": 5,
"pricePerPax": 200,
"totalPrice": 1000,
"fee": 100
},
{
"count": 1,
"pricePerPax": 200,
"totalPrice": 200,
"fee": 10
}
]
},
{
"name":"bannana with island tour",
"maxPax":10,
"isAvailableDayTime":[
9,10,11,12,13,15,16,17,18,
33,34,35,36,37,39,38,39,40,
56,57,58,59,60,62,63,64,65,
80,81,82,83,84,86,87,88,89,
104,105,106,107,108,110,111,112,113,
128,129,130,131,132,134,135,136,137,
152,153,154,155,156,158,159,160,161
],
"inventoryNeededSet":[
{
"inventoryId": 1,
"count":2
},
{
"inventoryId": 1,
"count":2
}
],
"paxPrices": [
{
"count": 5,
"pricePerPax": 200,
"totalPrice": 1000,
"fee": 100
},
{
"count": 1,
"pricePerPax": 200,
"totalPrice": 200,
"fee": 10
}
]
}
],
"photos": [
"https://samplephoto1.com",
"https://samplephoto2.com",
"https://samplephoto3.com"
],
"videos": [
"https://samplevid1.com",
"https://samplevid2.com",
"https://samplevid3.com"
],
"why": "sample why",
"description": "sample desc",
"cancellationPolicy":"cancellationPolicy",
"displayPrice": 300,
"displayDiscounted": 250,
"displayMaxPax": 2
}
the thing is, I want to save the blockdate, what is the syntax of inserting the blockdates?
=======================UPDATED======================
Try this before stringifying the data variable:
data.blockdates = $("#block-dates").val();
To execute your code jQuery is needed. Try after inserting <script src='https://code.jquery.com/jquery-3.3.1.min.js'></script> before your code.
If you have let blockdates = $("#block-dates").val();
You can append blockdates into data like this
data['blockdates']=blockdates;
You may need to keep the elements in an object first. You can then add them to the array.
blockDates= [];
var description = $("#card-description").val();
var notAvailableDate = $("##block-dates").val();
var blockdate = {description, notAvailableDate};
blockDates.push(blockdate);
in this way => let content = ajax("api/unitContents", JSON.stringify(data, blockDates), "POST");
or
let data = {
"title": title,
"catalogId": catalogId,
"categoryId": categoryId,
"subcategoryId": subcategoryId,
"why": why,
"cancellationPolicy": cancellationPolicy,
"displayPrice": displayPrice,
"displayDiscounted": displayDiscounted,
"displayMaxPax": displayMaxPax,
"blockDates": blockDates
};
in this way => `let content = ajax("api/unitContents", JSON.stringify(data), "POST");`