I have an array that contains an ID and also a parent_ID. I need to figure out a way to list all objects in the array that share the same parent. The data that generates this array is dynamic and can go up multiple levels deep in some instances.
example array
0: {id: "1", parent_id: "0", name: "Greater New York"...}
1: {id: "2", parent_id: "0", name: "Eastern New York"...}
2: {id: "1001", parent_id: "2", name: "Suffolk"...}
3: {id: "1002", parent_id: "2", name: "Nassau"...}
4: {id: "1003", parent_id: "1", name: "Eastern Long Island"...}
5: {id: "1005", parent_id: "1", name: "Bronx"...}
6: {id: "1006", parent_id: "1", name: "Brooklyn"...}
7: {id: "1007", parent_id: "1", name: "Kings Bay"...}
8: {id: "1008", parent_id: "1", name: "Manhattan"...}
9: {id: "1009", parent_id: "1046", name: "Mid-Hudson"...}
10: {id: "1014", parent_id: "1", name: "Westchester"...}
11: {id: "1015", parent_id: "2", name: "Metro"...}
12: {id: "1016", parent_id: "2", name: "Queens"...}
13: {id: "1017", parent_id: "2", name: "Western Queens"...}
14: {id: "1045", parent_id: "1", name: "Lower Hudson"...}
15: {id: "1046", parent_id: "0", name: "North Hudson"...}
16: {id: "1047", parent_id: "1046", name: "Albany"...}
17: {id: "1048", parent_id: "1046", name: "Berkshire County"...}
18: {id: "1049", parent_id: "1046", name: "Mohawk River"...}
19: {id: "1050", parent_id: "1046", name: "Southern Adirondack"...}
20: {id: "1051", parent_id: "1046", name: "Green Mountain"...}
Right now i have my JSX returning checkboxes in the order that is put out from the array.
{areas.map(area => (
<div className="col-12 mb-2" key={area.id}>
<input data-layout={area.type} type="checkbox" value={area.id}
onChange={props.onChange}/>
<label className="ml-3 mb-0">{area.name}</label>
</div>
))}
what i need to do is match the the parent_id to the id and group them all together,
so all with parent_id: 0 will be top level, then everything will fall under that.
Greater New York
Eastern Long Island
Bronx
Brooklyn
Kings Bay
Manhattan
Westchester
Lower Hudson
Eastern New York
Suffolk
Nassau
Metro
Queens
Western Queens
North Hudson
Mid Hudson
Albany
Berkshire County
Mohawk River
Southern Adarondack
Green Mountain
Any help formulating this logic would be greatly appreciated.
Edit: All i can find to filter is
{areas.filter(area => area.id ===
area.parent_id).map(filteredArea => (
<li>{filteredArea}</li>
))}
I've played with multiple variations of this, including making a separate array for the parent ID's.
If you are trying to group objects by parent_id, below code will be able to help.
let groupBy = (array, key) => {
return array.reduce((result, obj) => {
(result[obj[key]] = result[obj[key]] || []).push(obj);
return result;
}, {});
};
groupBy(data,'parent_id');
Output :
{
'0': [
{ id: '1', parent_id: '0', name: 'Greater New York' },
{ id: '2', parent_id: '0', name: 'Eastern New York' },
{ id: '1046', parent_id: '0', name: 'North Hudson' }
],
'1': [
{ id: '1003', parent_id: '1', name: 'Eastern Long Island' },
{ id: '1005', parent_id: '1', name: 'Bronx' },
{ id: '1006', parent_id: '1', name: 'Brooklyn' },
{ id: '1007', parent_id: '1', name: 'Kings Bay' },
{ id: '1008', parent_id: '1', name: 'Manhattan' },
{ id: '1014', parent_id: '1', name: 'Westchester' },
{ id: '1045', parent_id: '1', name: 'Lower Hudson' }
],
'2': [
{ id: '1001', parent_id: '2', name: 'Suffolk' },
{ id: '1002', parent_id: '2', name: 'Nassau' },
{ id: '1015', parent_id: '2', name: 'Metro' },
{ id: '1016', parent_id: '2', name: 'Queens' },
{ id: '1017', parent_id: '2', name: 'Western Queens' }
],
'1046': [
{ id: '1009', parent_id: '1046', name: 'Mid-Hudson' },
{ id: '1047', parent_id: '1046', name: 'Albany' },
{ id: '1048', parent_id: '1046', name: 'Berkshire County' },
{ id: '1049', parent_id: '1046', name: 'Mohawk River' },
{ id: '1050', parent_id: '1046', name: 'Southern Adirondack' },
{ id: '1051', parent_id: '1046', name: 'Green Mountain' }
]
}
You can then use this list to generate your <li> elements
Related
In a small ecommerce project (sourcing data from WooCommerce) in ReactJs i have a variable product
Besides all the product data i got two array object representing the product variations, one contains all the available attribute and options:
nodes: Array(3)
0:
id: "d2VpZ2h0OjMxOldlaWdodA=="
name: "Weight"
options: Array(2)
0: "250gr"
1: "500gr"
position: 0
variation: true
visible: true
1:
id: "cm9hc3Q6MzE6Um9hc3Q="
name: "Roast"
options: Array(3)
0: "Light"
1: "Medium"
2: "Dark"
position: 1
variation: true
visible: true
2:
id: "cGFja2FnaW5nOjMxOlBhY2thZ2luZw=="
name: "Packaging"
options: Array(2)
0: "Card"
1: "Tin"
position: 2
variation: true
visible: true
I save this one in a state and use it to build the select (3 select in this case)
then i have an array of object which contans all the available combinations, with price, id and so on:
nodes: Array(5)
0:
attributes:
nodes: Array(3)
0: {id: "NDB8fHdlaWdodHx8MjUwZ3I=", name: "weight", value: "250gr"}
1: {id: "NDB8fHJvYXN0fHxNZWRpdW0=", name: "roast", value: "Medium"}
2: {id: "NDB8fHBhY2thZ2luZ3x8Q2FyZA==", name: "packaging", value: "Card"}
id: "cHJvZHVjdF92YXJpYXRpb246NDA="
price: "€7,00"
variationId: 40
1:
attributes:
nodes: Array(3)
0: {id: "Mzh8fHdlaWdodHx8NTAwZ3I=", name: "weight", value: "500gr"}
1: {id: "Mzh8fHJvYXN0fHxEYXJr", name: "roast", value: "Dark"}
2: {id: "Mzh8fHBhY2thZ2luZ3x8VGlu", name: "packaging", value: "Tin"}
length: 3
id: "cHJvZHVjdF92YXJpYXRpb246Mzg="
price: "€12,00"
variationId: 38
2:
attributes:
nodes: Array(3)
0: {id: "Mzd8fHdlaWdodHx8NTAwZ3I=", name: "weight", value: "500gr"}
1: {id: "Mzd8fHJvYXN0fHxNZWRpdW0=", name: "roast", value: "Medium"}
2: {id: "Mzd8fHBhY2thZ2luZ3x8VGlu", name: "packaging", value: "Tin"}
length: 3
id: "cHJvZHVjdF92YXJpYXRpb246Mzc="
price: "€12,00"
variationId: 37
3:
attributes:
nodes: Array(3)
0: {id: "MzZ8fHdlaWdodHx8NTAwZ3I=", name: "weight", value: "500gr"}
1: {id: "MzZ8fHJvYXN0fHxMaWdodA==", name: "roast", value: "Light"}
2: {id: "MzZ8fHBhY2thZ2luZ3x8VGlu", name: "packaging", value: "Tin"}
id: "cHJvZHVjdF92YXJpYXRpb246MzY="
price: "€12,00"
variationId: 36
4:
attributes:
nodes: Array(3)
0: {id: "MzR8fHdlaWdodHx8MjUwZ3I=", name: "weight", value: "250gr"}
1: {id: "MzR8fHJvYXN0fHxMaWdodA==", name: "roast", value: "Light"}
2: {id: "MzR8fHBhY2thZ2luZ3x8Q2FyZA==", name: "packaging", value: "Card"}
length: 3
id: "cHJvZHVjdF92YXJpYXRpb246MzQ="
price: "€7,00"
variationId: 34
Basically, when i select something on any select, the other select shoould filter based on the avaialble variations: if i select 250gr as weight, the Dark Roast and the Tin Packaging sould be removed from their select since they arent combinable with 250gr; if i switch back to 500gr (or to "no option selected") they should reappear in the same place as they were before.
on the basic WooCommerce product page it already works this way (you can check its behaviour here: https://shop.popland.it/prodotto/coffee-bean/) but replicating it in ReactJs its harder than i was thinking.
At the moment im stuck on loop that generate the select with an empty onChange handler:
const [attr, setAttr] = useState(product.attributes);
<div>
{attr.nodes.map((attribute, l) => {
return (
<div key={l}>
<span>{attribute.name}</span>
<select
id={attribute.name}
onChange={handleChange}
data-attribute_name={`attribute_${attribute.name}`}
>
<option>Select option</option>
{attribute.options.map((option, o) => {
return (
<option key={o} value={option}>
{option}
</option>
);
})}
</select>
</div>
);
})}
</div>
Any suggetion/help on how to go on from here?
here is my solution.
/src/hooks.js
import { useState } from "react";
import { filterVariations, formatVariations } from "./helpers";
export function useVariations(product) {
const [state, setState] = useState({});
const filteredVariations = filterVariations(
product?.variations?.nodes,
state,
);
const formatedVariations = formatVariations(
filteredVariations,
product?.variations?.nodes,
);
return [formatedVariations, state, setState];
}
/src/helpers.js
export function filterVariations(variations, state) {
if (Object.keys(state).length === 0) {
return variations;
}
return Object.keys(state)?.reduce((accStateVars, currStateVar) => {
return accStateVars.reduce((accVars, currVar) => {
const filteredAttrsByName = currVar?.attributes?.nodes?.filter(
(attr) => currStateVar === attr?.name,
);
const withSelected = currVar?.attributes?.nodes?.findIndex(
(attr) => attr?.attributeId === state?.[currStateVar]?.value,
);
return [
...accVars,
{
attributes: {
nodes:
withSelected >= 0
? currVar?.attributes?.nodes
: filteredAttrsByName,
},
},
];
}, []);
}, variations);
}
export function formatVariations(filteredVariations, variations) {
const defaultSelects = variations?.reduce(
(accVars, currVar) => ({
...accVars,
...currVar?.attributes?.nodes?.reduce(
(accAttrs, currAttr) => ({ ...accAttrs, [currAttr.name]: {} }),
{},
),
}),
{},
);
return filteredVariations.reduce((accVars, currVar) => {
const filteredAttrs = currVar?.attributes?.nodes?.reduce(
(accAttrs, currAttr) => {
const exists =
0 <=
accVars[currAttr.name]?.options?.findIndex(
(option) => option.value === currAttr.attributeId,
);
return {
...accAttrs,
[currAttr.name]: {
placeholder: currAttr.label,
options: exists
? accVars[currAttr.name]?.options || []
: [
...(accVars[currAttr.name]?.options || []),
{ label: currAttr.value, value: currAttr.attributeId },
],
},
};
},
{},
);
return { ...accVars, ...filteredAttrs };
}, defaultSelects);
}
/src/App.js
import "./styles.css";
import Select from "react-select";
import { useVariations } from "./hooks";
const product = {
variations: {
nodes: [
{
attributes: {
nodes: [
{
name: "pa_size",
attributeId: 254,
id: "NTY5MHx8cGFfc2l6ZXx8MTItc3BlYWtlcg==",
label: "Size",
value: '12" Speaker',
},
{
name: "pa_color",
attributeId: 304,
id: "NTY5MHx8cGFfY29sb3J8fGdyYXBoaXRl",
label: "Color",
value: "Graphite",
},
{
name: "pa_flavor",
attributeId: 320,
id: "NTY5MHx8cGFfZmxhdm9yfHxnb2xk",
label: "Flavor",
value: "Gold",
},
{
name: "pa_pallet",
attributeId: 336,
id: "NTY5MHx8cGFfcGFsbGV0fHxncmVlbg==",
label: "Pallet",
value: "Green",
},
],
},
},
{
attributes: {
nodes: [
{
name: "pa_size",
attributeId: 255,
id: "NTY4Nnx8cGFfc2l6ZXx8MTAtc3BlYWtlcg==",
label: "Size",
value: '10" Speaker',
},
{
name: "pa_color",
attributeId: 67,
id: "NTY4Nnx8cGFfY29sb3J8fGJlaWdl",
label: "Color",
value: "Beige",
},
{
name: "pa_flavor",
attributeId: 320,
id: "NTY4Nnx8cGFfZmxhdm9yfHxnb2xk",
label: "Flavor",
value: "Gold",
},
{
name: "pa_pallet",
attributeId: 337,
id: "NTY4Nnx8cGFfcGFsbGV0fHxwZWFjaA==",
label: "Pallet",
value: "Peach",
},
],
},
},
{
attributes: {
nodes: [
{
name: "pa_size",
attributeId: 255,
id: "NTY4N3x8cGFfc2l6ZXx8MTAtc3BlYWtlcg==",
label: "Size",
value: '10" Speaker',
},
{
name: "pa_color",
attributeId: 439,
id: "NTY4N3x8cGFfY29sb3J8fGZhdGFsLWFwcGxl",
label: "Color",
value: "Fatal Apple",
},
{
name: "pa_flavor",
attributeId: 319,
id: "NTY4N3x8cGFfZmxhdm9yfHx2YW5pbGxh",
label: "Flavor",
value: "Vanilla",
},
{
name: "pa_pallet",
attributeId: 336,
id: "NTY4N3x8cGFfcGFsbGV0fHxncmVlbg==",
label: "Pallet",
value: "Green",
},
],
},
},
{
attributes: {
nodes: [
{
name: "pa_size",
attributeId: 254,
id: "NTY4OHx8cGFfc2l6ZXx8MTItc3BlYWtlcg==",
label: "Size",
value: '12" Speaker',
},
{
name: "pa_color",
attributeId: 67,
id: "NTY4OHx8cGFfY29sb3J8fGJlaWdl",
label: "Color",
value: "Beige",
},
{
name: "pa_flavor",
attributeId: 320,
id: "NTY4OHx8cGFfZmxhdm9yfHxnb2xk",
label: "Flavor",
value: "Gold",
},
{
name: "pa_pallet",
attributeId: 337,
id: "NTY4OHx8cGFfcGFsbGV0fHxwZWFjaA==",
label: "Pallet",
value: "Peach",
},
],
},
},
{
attributes: {
nodes: [
{
name: "pa_size",
attributeId: 254,
id: "NTY4OXx8cGFfc2l6ZXx8MTItc3BlYWtlcg==",
label: "Size",
value: '12" Speaker',
},
{
name: "pa_color",
attributeId: 436,
id: "NTY4OXx8cGFfY29sb3J8fGJlbGdyYXZlcw==",
label: "Color",
value: "Belgraves",
},
{
name: "pa_flavor",
attributeId: 319,
id: "NTY4OXx8cGFfZmxhdm9yfHx2YW5pbGxh",
label: "Flavor",
value: "Vanilla",
},
{
name: "pa_pallet",
attributeId: 336,
id: "NTY4OXx8cGFfcGFsbGV0fHxncmVlbg==",
label: "Pallet",
value: "Green",
},
],
},
},
],
},
};
export default function App() {
const [selects, state, setState] = useVariations(product);
function onChange(select, value) {
const newState = {
...state,
[select]: { ...value, name: select },
};
if (!value) {
delete newState[select];
}
setState(newState);
}
return (
<div className="App">
{Object.keys(selects).map((select) => (
<Select
isClearable
key={selects[select].placeholder}
placeholder={selects[select].placeholder}
// value={state[select]}
onChange={(o) => onChange(select, o)}
options={selects[select].options}
/>
))}
</div>
);
}
Playground
I have an first array like this
[
["Maths", "Chemistry", "Physics"],
["CS", "EC"],
["High", "Medium", "Low", "Average", "Excellent"]
]
And I have an another array of object in the below format
[
[{
id: 1,
name: "Maths",
is_active: 1
},
{
id: 2,
name: "Chemistry",
is_active: 1
},
{
id: 3,
name: "Physics",
is_active: 1
},
{
id: 4,
name: "Social Science",
is_active: 1
}
],
[{
id: 10,
name: "CS",
is_active: 1
},
{
id: 11,
name: "EC",
is_active: 1
},
{
id: 12,
name: "PHY",
is_active: 1
},
],
[{
id: 101,
name: "High",
is_active: 1
},
{
id: 102,
name: "Low",
is_active: 1
},
{
id: 103,
name: "Medium",
is_active: 1
},
{
id: 104,
name: "Excellent",
is_active: 1
},
{
id: 105,
name: "Average",
is_active: 1
},
{
id: 106,
name: "Below Average",
is_active: 1
},
]
]
I need to replace the first array values with id by matching the names present in first array with name present in the nested array of objects in second array.
My Final Output need to be in this format
[
[1,2,3],
[10,11],
[101,103,102,105,104]
]
Can Anyone help me how to do this in TypeScript.
I can suggest using map() and find() this :
simpleData is your table containing only the names
fullData is your table containing your objects
let fullData = [
[{
id: 1,
name: "Maths",
is_active: 1
},
{
id: 2,
name: "Chemistry",
is_active: 1
},
{
id: 3,
name: "Physics",
is_active: 1
},
{
id: 4,
name: "Social Science",
is_active: 1
}
],
[{
id: 10,
name: "CS",
is_active: 1
},
{
id: 11,
name: "EC",
is_active: 1
},
{
id: 12,
name: "PHY",
is_active: 1
},
],
[{
id: 101,
name: "High",
is_active: 1
},
{
id: 102,
name: "Low",
is_active: 1
},
{
id: 103,
name: "Medium",
is_active: 1
},
{
id: 104,
name: "Excellent",
is_active: 1
},
{
id: 105,
name: "Average",
is_active: 1
},
{
id: 106,
name: "Below Average",
is_active: 1
},
]
]
let simpleData = [
["Maths", "Chemistry", "Physics"],
["CS", "EC"],
["High", "Medium", "Low", "Average", "Excellent"]
]
let newIdTable = [];
for ( let i = 0; i < fullData.length; i++ ) {
let table = simpleData[i].map( ( name ) => {
return fullData[i].find( item => item.name === name ).id
} );
newIdTable.push( table );
}
console.log(newIdTable)
Using find(), if the corresponding object doesn't exist it will return undefined. I didn't test the case here, because I supposed that your object already exist in the fullData table. So you have to modify the code with a condition to handle that case if you need :)
I have this array
array = [
{id: "one", title: "new 1"},
{id: "two", parent_id: "132132", title: "new 2"},
{id: "three", parent_id: "132132", title: "new 3"},
{id: "four", parent_id: "132132", title: "new 1"},
{id: "one", parent_id: "132132", title: "new 1"}
]
We need
array = [
{id: "two", parent_id: "132132", title: "new 2"},
{id: "three", parent_id: "132132", title: "new 3"},
{id: "four", parent_id: "132132", title: "new 1"},
{id: "one", parent_id: "132132", title: "new 1"}
]
We need to compare elements to get unique array with different avoiding other elements
I have tried using this method
uniqueArray = (arr) => {
return arr.filter((e, i, arr) => arr.findIndex(e2 => Object.keys(e2).every(prop => e2[prop] === e[prop])) === i);
};
I prefer Array.reduce for this kind of things:
const filteredArr = arr.reduce((acc, current) => {
const exists = acc.find(item => item.id === current.id);
if (!exists) {
return acc.concat([current]);
} else {
return acc;
}
}, []);
If I understand you correctly, you want to return object without the property of parentId. If so you can use this.
array.filter(arr => arr.hasOwnProperty("parentId"))
How can i sort the data and print in react.
which libraries do i need to use ?
here is the data which is to be sorted field wise
data = [{
key: 1,
name: 'Steve',
city: 'Paris',
}, {
key: 2,
name: 'Tim',
city: 'London',
}, {
key: 3,
name: 'Stella',
city: 'Bankok',
}, {
key: 4,
name: 'John',
city: 'Paris',
}];
Use Array.prototype.sort() for this.
Check this example:
data = [{
key: 1,
name: 'Steve',
city: 'Paris',
}, {
key: 2,
name: 'Tim',
city: 'London',
}, {
key: 3,
name: 'Stella',
city: 'Bankok',
}, {
key: 4,
name: 'John',
city: 'Paris',
}];
data.sort((a,b) => a.name > b.name);
console.log('updated data', data)
I'm using this getorgchart library to generate organization chart in my application. I just want to highlight a particular node, i.e. the user who has logged in the application his node should be highlighted.
// Code goes here
var orgChart = new getOrgChart(document.getElementById("people"), {
theme: "monica",
primaryFields: ["name", "title"],
photoFields: ["image"],
gridView: true,
linkType: "B",
dataSource: [
{ id: 1, parentId: null, name: "Amber McKenzie", title: "CEO", phone: "678-772-470", mail: "lemmons#jourrapide.com", adress: "Atlanta, GA 30303", image: "images/f-11.jpg" },
{ id: 2, parentId: 1, name: "Ava Field", title: "Paper goods machine setter", phone: "937-912-4971", mail: "anderson#jourrapide.com", image: "images/f-22.jpg" },
{ id: 3, parentId: 1, name: "Evie Johnson", title: "Employer relations representative", phone: "314-722-6164", mail: "thornton#armyspy.com", image: "images/f-24.jpg" },
{ id: 6, parentId: 2, name: "Rebecca Randall", title: "Optometrist", phone: "801-920-9842", mail: "JasonWGoodman#armyspy.com", image: "images/f-8.jpg" },
{ id: 7, parentId: 2, name: "Spencer May", title: "System operator", phone: "Conservation scientist", mail: "hodges#teleworm.us", image: "images/f-7.jpg" },
{ id: 8, parentId: 3, name: "Max Ford", title: "Budget manager", phone: "989-474-8325", mail: "hunter#teleworm.us", image: "images/f-6.jpg" },
{ id: 9, parentId: 3, name: "Riley Bray", title: "Structural metal fabricator", phone: "479-359-2159", image: "images/f-3.jpg" }
],
customize: {
"1": { color: "green" },
"2": { theme: "deborah" },
"3": { theme: "deborah", color: "darkred" }
}
});
Here
customize: {
"1": { color: "green" },
"2": { theme: "deborah" },
"3": { theme: "deborah", color: "darkred" }
}
u can customize for particular Id based on your login data id you can customize and make it highlight