Reputation: 27
I could use some help with the following:
I'm trying to create a filterable wordpress nav menu using React Tree Menu.
The Tree Menu component requires the following data structure:
{
"Home" : {
checkbox: false,
ID: 1,
children: {
"Getting Started" : {
checkbox: false,
ID: 47,
slug: 'getting-started',
},
"Interaction Design Principles": {
checkbox: false,
children: {
"Design Principle the First" : {
selected: false,
checkbox: false,
ID: 67
}
}
}
}
},
"UPS Mobile (iOs, Android)" : {
checkbox: false,
children: {
"Overview" : {
checkbox: false,
ID: 22
},
"Reference" : {
checkbox: false,
ID: 14
}
}
},
"mDot" : {
checkbox: false,
children: {
"Elements" : {
checkbox: false,
ID: 19,
children: {
"Navigation" : {
checkbox: false,
ID: 90
}
}
},
}
}
}
I have set up parent and child pages of the above in wordpress and have also created a hierarchical wordpress menu. I am using the wordpress menu api
which returns the following data structure:
[
{
"ID": 46,
"order": 1,
"parent": 0,
"title": "Home",
"attr": "",
"target": "",
"classes": "",
"xfn": "",
"description": "",
"object_id": 2,
"object": "page",
"type": "post_type",
"type_label": "Page",
"children": [
{
"ID": 47,
"order": 2,
"parent": 46,
"title": "Getting Started",
"url": "http://mobilestyle.ups.dev/home/getting-started/",
"attr": "",
"target": "",
"classes": "",
"xfn": "",
"description": "",
"object_id": 15,
"object": "page",
"type": "post_type",
"type_label": "Page",
"children": []
},
{
"ID": 48,
"order": 3,
"parent": 46,
"title": "Interaction Design Principles",
"url": "http://mobilestyle.ups.dev/home/interaction-design-principles/",
"attr": "",
"target": "",
"classes": "",
"xfn": "",
"description": "",
"object_id": 22,
"object": "page",
"type": "post_type",
"type_label": "Page",
"children": [
{
"ID": 49,
"order": 4,
"parent": 48,
"title": "Design Principle the First",
"url": "http://mobilestyle.ups.dev/home/interaction-design-principles/design-principle-the-first/",
"attr": "",
"target": "",
"classes": "",
"xfn": "",
"description": "",
"object_id": 24,
"object": "page",
"type": "post_type",
"type_label": "Page",
"children": []
}
]
}
]
},
{
"ID": 50,
"order": 5,
"parent": 0,
"title": "mDot",
"url": "http://mobilestyle.ups.dev/mdot/",
"attr": "",
"target": "",
"classes": "",
"xfn": "",
"description": "",
"object_id": 8,
"object": "page",
"type": "post_type",
"type_label": "Page",
"children": [
{
"ID": 51,
"order": 6,
"parent": 50,
"title": "Elements",
"url": "http://mobilestyle.ups.dev/mdot/elements/",
"attr": "",
"target": "",
"classes": "",
"xfn": "",
"description": "",
"object_id": 30,
"object": "page",
"type": "post_type",
"type_label": "Page",
"children": [
{
"ID": 52,
"order": 7,
"parent": 51,
"title": "Navigation",
"url": "http://mobilestyle.ups.dev/mdot/elements/navigation/",
"attr": "",
"target": "",
"classes": "",
"xfn": "",
"description": "",
"object_id": 32,
"object": "page",
"type": "post_type",
"type_label": "Page",
"children": []
}
]
}
]
},
{
"ID": 54,
"order": 8,
"parent": 0,
"title": "UPS Mobile (iOS, Android)",
"url": "http://mobilestyle.ups.dev/ups-mobile/",
"attr": "",
"target": "",
"classes": "",
"xfn": "",
"description": "",
"object_id": 13,
"object": "page",
"type": "post_type",
"type_label": "Page",
"children": [
{
"ID": 55,
"order": 9,
"parent": 54,
"title": "Overview",
"url": "http://mobilestyle.ups.dev/ups-mobile/overview/",
"attr": "",
"target": "",
"classes": "",
"xfn": "",
"description": "",
"object_id": 26,
"object": "page",
"type": "post_type",
"type_label": "Page",
"children": []
},
{
"ID": 56,
"order": 10,
"parent": 54,
"title": "Reference",
"url": "http://mobilestyle.ups.dev/ups-mobile/reference/",
"attr": "",
"target": "",
"classes": "",
"xfn": "",
"description": "",
"object_id": 28,
"object": "page",
"type": "post_type",
"type_label": "Page",
"children": []
}
]
}
]
Can someone please help me turn what I receive from the wordpress menu api into what the Tree Menu component expects?
Thanks in advance for any help. -Ian
Upvotes: 2
Views: 691
Reputation: 50797
Here's a pretty simple recursive version:
const buildMenu = (xs) =>
xs .reduce ((a, {title, ID, children}) => ((a [title] = {
checkbox: false, ID, ... (children .length ? {children: buildMenu (children)} : {})
}), a), {})
const source = [{ID: 46, order: 1, parent: 0, title: "Home", attr: "", target: "", classes: "", xfn: "", description: "", object_id: 2, object: "page", type: "post_type", type_label: "Page", children: [{ID: 47, order: 2, parent: 46, title: "Getting Started", url: "http://mobilestyle.ups.dev/home/getting-started/", attr: "", target: "", classes: "", xfn: "", description: "", object_id: 15, object: "page", type: "post_type", type_label: "Page", children: []}, {ID: 48, order: 3, parent: 46, title: "Interaction Design Principles", url: "http://mobilestyle.ups.dev/home/interaction-design-principles/", attr: "", target: "", classes: "", xfn: "", description: "", object_id: 22, object: "page", type: "post_type", type_label: "Page", children: [{ID: 49, order: 4, parent: 48, title: "Design Principle the First", url: "http://mobilestyle.ups.dev/home/interaction-design-principles/design-principle-the-first/", attr: "", target: "", classes: "", xfn: "", description: "", object_id: 24, object: "page", type: "post_type", type_label: "Page", children: []}]}]}, {ID: 50, order: 5, parent: 0, title: "mDot", url: "http://mobilestyle.ups.dev/mdot/", attr: "", target: "", classes: "", xfn: "", description: "", object_id: 8, object: "page", type: "post_type", type_label: "Page", children: [{ID: 51, order: 6, parent: 50, title: "Elements", url: "http://mobilestyle.ups.dev/mdot/elements/", attr: "", target: "", classes: "", xfn: "", description: "", object_id: 30, object: "page", type: "post_type", type_label: "Page", children: [{ID: 52, order: 7, parent: 51, title: "Navigation", url: "http://mobilestyle.ups.dev/mdot/elements/navigation/", attr: "", target: "", classes: "", xfn: "", description: "", object_id: 32, object: "page", type: "post_type", type_label: "Page", children: []}]}]}, {ID: 54, order: 8, parent: 0, title: "UPS Mobile (iOS, Android)", url: "http://mobilestyle.ups.dev/ups-mobile/", attr: "", target: "", classes: "", xfn: "", description: "", object_id: 13, object: "page", type: "post_type", type_label: "Page", children: [{ID: 55, order: 9, parent: 54, title: "Overview", url: "http://mobilestyle.ups.dev/ups-mobile/overview/", attr: "", target: "", classes: "", xfn: "", description: "", object_id: 26, object: "page", type: "post_type", type_label: "Page", children: []}, {ID: 56, order: 10, parent: 54, title: "Reference", url: "http://mobilestyle.ups.dev/ups-mobile/reference/", attr: "", target: "", classes: "", xfn: "", description: "", object_id: 28, object: "page", type: "post_type", type_label: "Page", children: []}]}]
console .log (buildMenu (source))
.as-console-wrapper {max-height: 100% !important; top: 0}
We fold our array into an object, adding the property of the current title with a simple value consisting of the ID
, an arbitrarily false checkbox
attribute (is this actually derivable from the input?) and -- if our node has children -- the result of recurring on those children.
Upvotes: 0
Reputation: 10924
I'd use a recursive function to build the object you want. Something like the following:
function buildMenu(source, result) {
//build a return value if one wasn't passed in
result = result || {};
if (source && source.length) {
var item = source.shift(); //take first item from the array
result[item.title] = { ID : item.ID }; //make a new property in the result
//if there are children, build them recursively
if (item.children && item.children.length) {
result[item.title].children = buildMenu(item.children);
}
//build additional items recursively, based on the remaining items in the array
return buildMenu(source, result);
} else {
//none left, done
return result;
}
}
Call that function on your source array and it should work. There's a running example below if you want to try it out.
function buildMenu(source, result) {
result = result || {};
if (source && source.length) {
var item = source.shift();
result[item.title] = { ID : item.ID };
if (item.children && item.children.length) {
result[item.title].children = buildMenu(item.children);
}
return buildMenu(source, result);
} else {
return result;
}
}
var source = [
{
"ID": 46,
"order": 1,
"parent": 0,
"title": "Home",
"attr": "",
"target": "",
"classes": "",
"xfn": "",
"description": "",
"object_id": 2,
"object": "page",
"type": "post_type",
"type_label": "Page",
"children": [
{
"ID": 47,
"order": 2,
"parent": 46,
"title": "Getting Started",
"url": "http://mobilestyle.ups.dev/home/getting-started/",
"attr": "",
"target": "",
"classes": "",
"xfn": "",
"description": "",
"object_id": 15,
"object": "page",
"type": "post_type",
"type_label": "Page",
"children": []
},
{
"ID": 48,
"order": 3,
"parent": 46,
"title": "Interaction Design Principles",
"url": "http://mobilestyle.ups.dev/home/interaction-design-principles/",
"attr": "",
"target": "",
"classes": "",
"xfn": "",
"description": "",
"object_id": 22,
"object": "page",
"type": "post_type",
"type_label": "Page",
"children": [
{
"ID": 49,
"order": 4,
"parent": 48,
"title": "Design Principle the First",
"url": "http://mobilestyle.ups.dev/home/interaction-design-principles/design-principle-the-first/",
"attr": "",
"target": "",
"classes": "",
"xfn": "",
"description": "",
"object_id": 24,
"object": "page",
"type": "post_type",
"type_label": "Page",
"children": []
}
]
}
]
},
{
"ID": 50,
"order": 5,
"parent": 0,
"title": "mDot",
"url": "http://mobilestyle.ups.dev/mdot/",
"attr": "",
"target": "",
"classes": "",
"xfn": "",
"description": "",
"object_id": 8,
"object": "page",
"type": "post_type",
"type_label": "Page",
"children": [
{
"ID": 51,
"order": 6,
"parent": 50,
"title": "Elements",
"url": "http://mobilestyle.ups.dev/mdot/elements/",
"attr": "",
"target": "",
"classes": "",
"xfn": "",
"description": "",
"object_id": 30,
"object": "page",
"type": "post_type",
"type_label": "Page",
"children": [
{
"ID": 52,
"order": 7,
"parent": 51,
"title": "Navigation",
"url": "http://mobilestyle.ups.dev/mdot/elements/navigation/",
"attr": "",
"target": "",
"classes": "",
"xfn": "",
"description": "",
"object_id": 32,
"object": "page",
"type": "post_type",
"type_label": "Page",
"children": []
}
]
}
]
},
{
"ID": 54,
"order": 8,
"parent": 0,
"title": "UPS Mobile (iOS, Android)",
"url": "http://mobilestyle.ups.dev/ups-mobile/",
"attr": "",
"target": "",
"classes": "",
"xfn": "",
"description": "",
"object_id": 13,
"object": "page",
"type": "post_type",
"type_label": "Page",
"children": [
{
"ID": 55,
"order": 9,
"parent": 54,
"title": "Overview",
"url": "http://mobilestyle.ups.dev/ups-mobile/overview/",
"attr": "",
"target": "",
"classes": "",
"xfn": "",
"description": "",
"object_id": 26,
"object": "page",
"type": "post_type",
"type_label": "Page",
"children": []
},
{
"ID": 56,
"order": 10,
"parent": 54,
"title": "Reference",
"url": "http://mobilestyle.ups.dev/ups-mobile/reference/",
"attr": "",
"target": "",
"classes": "",
"xfn": "",
"description": "",
"object_id": 28,
"object": "page",
"type": "post_type",
"type_label": "Page",
"children": []
}
]
}
];
var dest = buildMenu(source);
console.log(dest);
Upvotes: 3