Design a customized menu using a JavaScript JSON array

Looking to generate a menu using JSON Array data

Here is the JSON Array:

[{
    "page_id":"102608802958096849","title":"Submenu 1 1","page_order":1,"parent_id":"305280635460611248","layout":"header","page_url":"submenu-1-1.html"
},{
    "page_id":"207782958260361106","title":"Submenu 2 1","page_order":1,"parent_id":"196241715470310788","layout":"header","page_url":"submenu-2-1.html"
},{
    "page_id":"305280635460611248","title":"Submenu 1","page_order":1,"parent_id":"308333626876055885","layout":"header","page_url":"submenu-1.html"
},{
    "page_id":"308333626876055885","title":"Demo","page_order":1,"parent_id":null,"layout":"header-slider","page_url":"index.html"
},{
    "page_id":"357018431614169959","title":"Not Mega Menu","page_order":1,"parent_id":"756836287653398147","layout":"header","page_url":"not-mega-menu.html"
},{
    "page_id":"363544895956322795","title":"Submenu 2 1 1","page_order":1,"parent_id":"207782958260361106","layout":"header","page_url":"submenu-2-1-1.html"
},{
    "page_id":"130518632716609153","title":"New Page","page_order":2,"parent_id":"756836287653398147","layout":"header","page_url":"new-page.html"
},{
    "page_id":"196241715470310788","title":"Submenu 2","page_order":2,"parent_id":"308333626876055885","layout":"header","page_url":"submenu-2.html"
},{
    "page_id":"520778073299851538","title":"Submenu 2 2","page_order":2,"parent_id":"196241715470310788","layout":"header","page_url":"submenu-2-2.html"
},{
    "page_id":"756836287653398147","title":"Phoenix","page_order":2,"parent_id":null,"layout":"header","page_url":"phoenix.html"
},{
    "page_id":"951287960823231869","title":"Submenu 2 1 2","page_order":2,"parent_id":"207782958260361106","layout":"header","page_url":"submenu-2-1-2.html"
}]

The desired menu structure should resemble the following:

HTML:

<ul>
<li>
    <a>Demo</a>
    <div>
        <ul>
            <li>
                <a>Submenu 1</a>
                <div>
                    <ul><li><a>Submenu 1 1</a></li></ul>
                </div>
            </li>
            <li>
                <a>Submenu 2</a>
                <div>
                    <ul>
                        <li>
                            <a>Submenu 2 1</a>
                            <div>
                                <ul>
                                    <li>
                                        <a>Submenu 2 1 1</a>
                                    </li>
                                    <li>
                                        <a>Submenu 2 1 2</a>
                                    </li>
                                </ul>
                            </div>
                        </li>
                        <li>
                            <a>Submenu 2 2</a>
                        </li>
                    </ul>
                </div>
            </li>
        </ul>
    </div>
</li>
<li>
    <a>Phoenix</a>
    <div>
        <ul>
            <li><a>New Page</a></li>
            <li><a>Not Mega Menu</a></li>
        </ul>
    </div>
</li>

Please note:

For example: "page_id":"102608802958096849","title":"Submenu 1 1","page_order":1,"parent_id":"305280635460611248","layout":"header","page_url":"submenu-1-1.html"

page_id = 102608802958096849 (defines the menu id)

title = Submenu 1 1 (the title of the menu item)

page_order = 1 (represents the position of the menu item)

Any suggestions on how to construct the above menu from the JSON array provided? Thank you in advance

Answer №1

To create the desired structure, you can start by constructing a tree.

function generateTree(arr) {
    var obj = {};
    arr.forEach(item => {
        if (obj[item.page_id] && obj[item.page_id].children) {
            item.children = obj[item.page_id] && obj[item.page_id].children;
        }
        obj[item.page_id] = item;
        obj[item.parent_id] = obj[item.parent_id] || {};
        obj[item.parent_id].children = obj[item.parent_id].children || [];
        obj[item.parent_id].children.push(item);
    });
    return obj.null.children;
}

function buildMenu(arr, target) {
    var ul = document.createElement('ul');

    arr.forEach(obj => {
        var li = document.createElement('li'),
            a = document.createElement('a'),
            div;

        a.appendChild(document.createTextNode(obj.title));
        a.href = obj.page_url;
        li.appendChild(a);
        if (obj.children) {
            div = document.createElement('div');
            buildMenu(obj.children, div);
            li.appendChild(div);
        }
        ul.appendChild(li);
    });
    target.appendChild(ul);
}

var data = [{ page_id: "102608802958096849", title: "Submenu 1 1", page_order: 1, parent_id: "305280635460611248", layout: "header", page_url: "submenu-1-1.html" }, { page_id: "207782958260361106", title: "Submenu 2 1", page_order: 1, parent_id: "196241715470310788", layout: "header", page_url: "submenu-2-1.html" }, { page_id: "305280635460611248", title: "Submenu 1", page_order: 1, parent_id: "30833362687...

buildMenu(data, document.body);

console.log(tree);

Answer №2

To start with, the best practice is to organize child objects within a parent object. This not only streamlines your process but also aligns with standard coding conventions.

[
  "Menu Item 1": {
    "page_url": "one.html",
    "submenus": [
      {
        "item": "Submenu 1-1",
        "page_url": "one-one.html",
      },
      {
        "item": "Submenu 1-2",
        "page_url": "one-two.html",
      }
    ],
  },
  "Menu Item 2": {
    "page_url": "two.html",
    "submenus": [
      {
        "item": "Submenu 2-1",
        "page_url": "two-one.html",
      },
      {
        "item": "Submenu 2-2",
        "page_url": "two-two.html",
      }
    ],
  }
]

From there, you can easily iterate through the submenu items and their corresponding links.

Answer №3

Initially, it is crucial to establish the connection between nodes and their respective parents in order to construct a tree structure:

 const map = {}, mainRoot = [];
 // Iterate through the array and destructure its elements:
 for(const {link_url, heading, link_id, parent_id} of array) {
    // Store each node in the map:
    let element;
    if(map[link_id]) {
      element = Object.assign(map[link_id], {link_url, heading});
    } else {
      element = map[link_id] = {link_url, heading, children: []};
    }

    // Establish parent-child relationships
    if(parent_id) {
      if(map[parent_id]) {
         map[parent_id].children.push(element);
      } else {
         map[parent_id] = { children: [ element ] };
      }
   } else {
      mainRoot.push(element);
   }
}

At this point, mainRoot holds a collection of root elements, with each having a children array containing child elements recursively. This enables an effortless creation of a DOM tree using recursion:

 function constructTree(array) {
   const container = document.createElement("li");
   for(const element of array) {
      const hyperlink = document.createElement("a");
      hyperlink.textContent = element.heading;
      hyperlink.href = element.link_url;
      container.appendChild(hyperlink);
      container.appendChild(constructTree(element.children));
   }
  return container;
}

Simply execute the following code snippet:

 document.body.appendChild(constructTree(mainRoot));

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Harness the power of loops to extract data from various URLs in JSON format using Selenium with Python

In our organization's HR system, I am utilizing Selenium in Python to parse data for people's profiles. However, I am facing some challenges with the process. I have a list of URLs and my goal is to extract information about individuals who repo ...

Guide to accessing the content within an h1 tag with JavaScript

I currently have a setup with 3 pages: 2 of them are WordPress pages while the other page is a custom page template featuring a form. The first two pages were created using the wp-job manager plugin. The first page includes a dropdown menu with a list of a ...

Obtaining the camera's rotation in radians using Three.js

I've been struggling to grasp the concepts of quaternions for quite some time now, and I suspect they may be the root cause of my current challenge. If you're familiar with three.js, you might know about the equirectangular panorama video exampl ...

Designing a straightforward thumbs-up icon

Hey there! I'm currently working on a blog application and trying to set up a simple like button for each post identified by its primary key (pk). However, I encountered an error along the way. The error message I received is "NoReverseMatch at /sing ...

When using Mongoose populate, it may either return an empty array or a list of Object

Currently, I am honing my skills in express.js by constructing a relational API but facing difficulty in populating keys within a schema. The structure involves having a list of properties, each with associated units. The units are linked through a proper ...

The latest URL is not launching in a separate tab

Looking for some assistance with this code snippet: <b-btn variant="primary" class="btn-sm" :disabled="updatePending || !row.enabled" @click="changeState(row, row.dt ? 'activate' : 'start&apo ...

Using JavaScript to identify the unlock screen on a website

I've been searching everywhere for a solution to my issue, but I haven't had any luck with Google or other websites. I'm currently working on creating a mobile website and I need assistance with redirecting users to the homepage in such a w ...

Using setRGB with BufferedImage results in inaccurate setColoring

When working with BufferedImages and using setRGB, I tried reapplying the exact RGBA byte values over the image to see if they worked. However, the result was a mutilated image. What could have possibly gone wrong? BufferedImage subImg = inputImage.getSub ...

Unleashing the power of JAX-RS with the magical @XmlIDREF

I've been stuck on this issue for hours now, it's probably a simple solution but I just can't seem to figure it out: Currently, I have an entity called Param that is being converted to JSON using jax-rs. This entity has a reference to anoth ...

Encountering a 401 Unauthorized error while attempting an AJAX call to an ASP.NET Web API endpoint that has Windows authentication activated

After creating a basic ASP.NET web API application, I implemented Cross-Origin Resource Sharing (CORS) using the Microsoft.AspNet.WebApi.Cors package. This is what my controller looks like: public class UserController : ApiController { [Route ...

Tips for including a hyperlink in a collapsible element within a dropdown menu using Bootstrap 5

Is there a way to add a link to "Home" and "Pages" that will collapse and show the list items below when clicked? I tried changing "#homeSubmenu" from a link to a href, but it does not collapse when clicked. <div class="wrapper"> & ...

PHP Multidimensional Array Magic

I'm grappling with a challenge where I need to merge elements from arrays that are common to each other into a new array. For example, if my initial array is: $array = [ [0,4], [1,2], [1,3], [3,2] ] The new array should look like this: $newarray = ...

Eliminating the appearance of horizontal scroll bar by employing transform scale to zoom out

When you run the code provided in the link below and scale down the HTML to 50% while increasing the width to fit the window, a scrollbar becomes visible. This only occurs in Chrome and not in Firefox. Click here The content of the DOM can be modified and ...

Using JavaScript to dynamically write content to the document in the

What is the correct way to write the HTML break tag "<br>" in JavaScript without it causing a line break? I want the tag to be displayed as text. For example, "the break tag in html is ..." See below for an example of what I am looking for. <scr ...

Ways to detect if there is a new database record and display it in the notification bar with an alert

In the Django framework, I am retrieving data through an AJAX request from a database like this: $.ajax({ url: '/activity/', type: 'GET', data:{}, success: function(data) { // alert(data); var div1 = doc ...

What steps can I take to make sure my JavaScript code accurately calculates numbers without resulting in undefined or NaN values?

I'm having an issue with my javascript code for a simple interest calculator. Every time I try to calculate the amount, it keeps returning NaN. It seems like the code is treating the + as if I'm trying to concatenate strings, and I'm not sur ...

What are the capabilities of an INNER JOIN query in Objection JS?

Here is the data model that I am working with: https://i.stack.imgur.com/g1T5i.jpg In this model, a User can be associated with multiple Projects, and a Project can have many Users. These relationships are managed through a join table called UserProjects. ...

Prevent storing each result value in a separate array when utilizing preg_match in PHP

Just starting out with PHP and attempting to extract data between two tags from an HTML file using preg_match. I managed to retrieve the data, but the issue is that each value is ending up in separate arrays as shown below: Array ( [0] => Bachelor ...

displaying information in table cells with jquery

Is there a way to display a table inside a td element with an on-click function without showing all tables in the same column when the function is triggered? I want the table to be shown only for the specific td that was clicked. $(document).ready(funct ...

Interacting with PHP through JavaScript function calls

I am facing some frustration with my website due to an issue involving PHP. When I retrieve data from a PHP file, it returns a JSON list like this: {"Data":{"Recipes":{"Recipe_5":{"ID":"5","TITLE":"Spaghetti Bolognese"},"Recipe_7":{"ID":"7","TITLE":"Wurst ...