What is the process for generating a tree structure from an HTML element?

This particular element is found within my Vue2 application:

<div class="child-elements-container draggable-container">
    <div>
        <div entity-type="entitytype1" type="elementType" id="2" class="single-element"></div>
        <div class="child-elements-container draggable-container">
            <div>
                <div entity-type="entitytype2" type="elementType" id="59" class="single-element"></div>
            </div>
        </div>
    </div>
    <div>
        <div entity-type="measures" type="elementType" id="3" class="single-element"></div>
        <div class="child-elements-container draggable-container">
            <div>
                <div entity-type="entitytype3" type="elementType" id="13" class="single-element"></div>
                <div class="child-elements-container draggable-container"></div>
            </div>
            <div>
                <div entity-type="entitytype2" type="elementType" id="14" class="single-element"></div>
                <div class="child-elements-container draggable-container"></div>
            </div>
        </div>
    </div>
    <div>
        <div entity-type="entitytype3" type="elementType" id="11" class="single-element">
        </div>
        <div class="child-elements-container draggable-container">
            <div>
                <div entity-type="entitytype3" type="elementType" id="12" class="single-element">
                </div>
                <div class="child-elements-container draggable-container"></div>
            </div>
        </div>
    </div>
</div>

The main goal is to obtain a tree structure utilizing the IDs of single-elements, and I am utilizing this function to visualize the hierarchy:

   buildDraggedHierarchy(el) {
            if (!el) {
                return [];
            }

            const children = [...el.querySelectorAll(":scope>div")];
            const output = children.map((child) => ({
                id: child.querySelector(".single-element") ? child.querySelector(".plan-element").id : null, 
                type: child.getAttribute("type"), 
                children: this.buildDraggedHierarchy(child.querySelector(".draggable-container")), 
            }));

            return output;
        },

However, the current output is as follows:

[
    {
        "id": "2",
        "type": null,
        "children": [
            {
                "id": "59",
                "type": null,
                "children": []
            }
        ]
    },
    {
        "id": "3",
        "type": null,
        "children": [
            {
                "id": "13",
                "type": null,
                "children": []
            },
            {
                "id": "14",
                "type": null,
                "children": []
            }
        ]
    },
    {
        "id": "11",
        "type": null,
        "children": [
            {
                "type": null,
                "children": []
            }
        ]
    }
]

It seems that the last element's children are not displayed correctly. It should include an ID of 12, but it is missing entirely. How can I resolve this issue?

Answer №1

There are a few issues that need to be addressed:

  • The function only includes a return statement for the base case when the argument is falsy, but not for other cases. The assignment to output doesn't serve much purpose as the variable is immediately released after being assigned. It would be more effective to return what is assigned to output.
  • The child element does not contain the id and type; it is nested one level deeper. Therefore, a selector is required to target it.

To resolve these issues, consider implementing the following code snippet:

const element = document.querySelector(".child-elements-container");
const elementHierarchy = this.buildDraggedHierarchy(element);
console.log(elementHierarchy);

function buildDraggedHierarchy(el) {
    if (!el) {
        return [];
    }
    let children = [...el.querySelectorAll(":scope>div")];
    return children.map((child) => {
        const elem = child.querySelector(".single-element");
        return {
            id: elem.id,
            type: elem.getAttribute("type"),
            children: this.buildDraggedHierarchy(child.querySelector(".draggable-container")),
        };
    });
}
<div class="child-elements-container draggable-container">
    <div>
        <div entity-type="entitytype1" type="elementType" id="2" class="single-element"></div>
        <div class="child-elements-container draggable-container">
            <div>
                <div entity-type="entitytype2" type="elementType" id="59" class="single-element"></div>
            </div>
        </div>
    </div>
    <div>
        <div entity-type="measures" type="elementType" id="3" class="single-element"></div>
        <div class="child-elements-container draggable-container">
            <div>
                <div entity-type="entitytype3" type="elementType" id="13" class="single-element"></div>
                <div class="child-elements-container draggable-container"></div>
            </div>
            <div>
                <div entity-type="entitytype2" type="elementType" id="14" class="single-element"></div>
                <div class="child-elements-container draggable-container"></div>
            </div>
        </div>
    </div>
    <div>
        <div entity-type="entitytype3" type="elementType" id="11" class="single-element">
        </div>
        <div class="child-elements-container draggable-container">
            <div>
                <div entity-type="entitytype3" type="elementType" id="12" class="single-element">
                </div>
                <div class="child-elements-container draggable-container"></div>
            </div>
        </div>
    </div>
</div>

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

Issue with the successful execution of connection event handler in NodeJS and Socket.io?

When I look at my code in files named server.js and index.html, I notice that the io.on('connection') part is not executing the console.log method in its callback when I visit my server in the web browser. Take a look at the code snippets below ...

Verify the value at a specific index within a Vuelidate array

I am working with a form array in Vuelidate and I have a requirement to validate one field based on the value of another field at the same index within the array. For example, I need the forename field to be required only if the surname field has been fil ...

Obtaining a URL in JavaScript

Hey there, I'm diving into the world of JavaScript and could use some guidance. I'm currently working on implementing forward and backward buttons on a webpage. The URL structure is http://webaddress.com/details?id=27 My goal is to write two fun ...

Tweenmax opacity will hold at 1 for a short period of time after the page has been reloaded

After implementing TweenMax from Gsap, I created a landing page intro with a loading container containing three divs, each with a h5 element positioned in the center using absolute positioning. Initially, I used StaggerFrom {opacity 0} to staggerTo {opacit ...

What is causing my Vue leave transition to malfunction?

Currently, I am utilizing vee validate for my form validation. Specifically, I have implemented vue transition to handle the display of validation errors in the following manner: <input type="text" name="name" v-validate="'required'"> < ...

Determine the Button's State by Monitoring Changes in the TextBox Text

I have been tasked with developing a web application for my company. The main components of the application are a button and a textbox. My goal is to allow users to input a value into the textbox, which will then be processed when they click on the button ...

getting v-model value updated when clicking button

How can I update the value of v-model DataJournals.Description in a looping data when a button is clicked? This is what I have attempted: template <tr v-for="(DataJournals, index) in DataJournal" :key="DataJournals.value"> <td> & ...

Contrast between using " and '

Similar Inquiry: When to Utilize Double or Single Quotes in JavaScript Comparison of single quotes and double quotes in JS As I delve into creating a Node.js Express web application, I've noticed that the tutorial consistently uses ' ins ...

instructions on invoking a function within the knockout $.getJSON() operation

I am currently experimenting with a basic knockout script (still in the learning process). $.getJSON(clientUrl + "/list/" + 1, function (data) { var viewModel = { clients: ko.observableArray(data) }; ko.applyBindings(viewModel); }); The initial arg ...

Working on rectifying the Chat Engine API code that was causing a 403 Status Code to be generated

Encountering a status code 403 while attempting to create a chat engine IO page, even though all authentication headers are believed to be accurate. Double-checked for typos but still unable to identify the issue. Despite console logging the user correctly ...

Firestore is failing to accept incoming data when the setDoc method is employed

I am encountering an issue with my app's connectivity to the Firestore database when attempting to utilize setDoc. The database is successfully operational for next-auth, creating records as intended. However, the problem arises when trying to enable ...

Ways to create a fixed button positioned statically at the bottom of a page

Currently, I am utilizing tailwind CSS to create a webpage with Next and Back buttons for navigation. However, an issue arises when there is minimal content on the page as the button adheres to the top. For visual reference, please view the image linked be ...

A guide to showcasing items based on their categories using React.js

After successfully displaying Categories from a port (http://localhost:5000), accessing my MongoDB database, I encountered an issue when attempting to display the products for each category separately. Despite trying the same method as before, I keep rec ...

What are the drawbacks of calling async/await within a fresh Promise() constructor?

I have implemented the async.eachLimit function to manage the maximum number of operations concurrently. const { eachLimit } = require("async"); function myFunction() { return new Promise(async (resolve, reject) => { eachLimit((await getAsyncArray ...

The interactions and functionalities of jQuery sortable and draggable elements

Looking for some assistance with a project involving draggable objects 'field' and 'container', along with a sortable object 'ui-main'. The goal is to drag the two aforementioned objects into 'ui-main', while also al ...

Evaluate One Input Value to Determine Another Input Value

Hey there, I've made an update to the fiddle but let me clarify what I'm trying to achieve. My goal is not to implement form validation as I already have that covered with the HTML5 "required" attribute. What I'm aiming for is to customize t ...

What is the purpose of returning a function in a React Hook?

Currently, I am incorporating Material-UI components into my project and have implemented the AutoComplete component in my application. While exploring an example provided by the Material-UI team, I stumbled upon a fascinating instance of using Ajax data ...

Issues with functionality arise when cloning HTML divs using JQuery

VIDEO I created a feature where clicking a button allows users to duplicate a note div. However, the copied note does not function like the original - it's not draggable and changing the color of the copied note affects the original note's color. ...

What is the process for removing an item from a JSON file using an HTTP DELETE request in a Node.js environment?

Essentially, I have a JSON file containing user and group data and I need to delete a specific group from it. Below is a snippet of the JSON file named authdata.json: [{ "name": "Allan", "role": ["Group Admin", "Super Admin"], "group": ["Cool- ...

Ways to stop Bootstrap collapse from displaying depending on a certain condition in bs5 framework

I've been struggling to figure out how to prevent a collapsible panel from opening or showing if a specific value is null. Despite multiple attempts, I haven't had any success. HTML <a href="#" data-bs-toggle="collapse" da ...