-3

I have a tree structure as follows which is rendered using jsTree:

Root
    Child 1
        Child 1 - 1
        Child 2 - 2
    Child 2
Root2
    Child 1

The tree is created dynamically by the user from the UI using a form and button clicks for adding nodes and attributes for each node. These attributes are collected using a form when the user clicks on a particular node. I am storing the node information in a list with node name and it's parent as follows:

<ul>
    <li data-node="Root 1" data-parent = ''>[Form to add attributes]</li>
    <li data-node="Child 1" data-parent="Root 1">[Form to add attributes]</li>
    <li data-node="Child 2" data-parent="Root 1">[Form to add attributes]</li>

... and so on.

I need to collect that data, in the following JSON format:

Root1: {
    formdata: {...}
    children: {
        Child 1: {
            formdata: {...}
            children: {
                Child 1 - 1: {
                    formdata: {...}
                }
                Child 1 - 2: {
                    formdata: {...}
                }
            }
        }
        Child 2: {
            formdata: {...}
            children: {
                Child 1 - 1: {
                    formdata: {...}
                }
            }
        }
    }
}

... and so on.

It could be N levels deep. I am only able to visualise collection going down one branch. If I dig into Root 1 > Child 1 > Child 1 - 1, I am not able to figure out how to come back to the parent, while maintaining the collected data.

Any help would be appreciated.

7
  • 1
    The first two data structures are unclear... Which language is that? If you have them in JSON, could you provide the literal JSON, or if it is a JavaScript object, could you provide the literal object syntax? You refer to the DOM. Can you provide some HTML + JS that demonstrates what you are doing? Commented Jul 26, 2019 at 9:50
  • 1
    Possible duplicate of Traversing a tree javascript Commented Jul 26, 2019 at 9:50
  • All of this is JavaScript, I have simply represented it without a language. Commented Jul 26, 2019 at 9:51
  • We need to have the HTML and JS, otherwise it will be guessing what you are working with. I vote to close this as too broad. Commented Jul 26, 2019 at 9:54
  • 5
    Parsing what? There is nothing in your question to parse. Only a sketch of some structure. Code needs real data to work, not just an idea. Now anyone that goes ahead and answers with some particular implementation choice will risk to get a reaction from you: "ok, but my HTML looks actually quite different, so this solution wont work for me". Commented Jul 26, 2019 at 10:00

1 Answer 1

1

After the edit to your question, it looks like that extra data are available as form inputs, or maybe the form is just the tool to end up with additional data- attributes on the li elements.

1. With FormData

I'll first assume these data are accessible via the standard FormData API. So for instance, if a form has <input name="country">, its value will be available under the country key.

Here is how you could build a tree object from scanning the DOM:

function collectTree(ul) {
    // Create the nodes & identify the root
    let nodes = {};
    let root = null;
    for (let li of ul.children) {
        // Extract form data using the FormData API
        let formdata = Object.fromEntries(new FormData(li.querySelector("form")).entries());
        nodes[li.dataset.node] = { formdata };
        if (!li.dataset.parent) root = nodes[li.dataset.node];
    }
    // Populate the children arrays
    for (let li of ul.children) {
        if (!li.dataset.parent) continue;
        let p = nodes[li.dataset.parent];
        if (!p.children) p.children = {};
        p.children[li.dataset.node] = nodes[li.dataset.node];
    }
    return root;
}

const root = collectTree(document.querySelector("ul"));

console.log(root);
<ul>
    <li data-node="Root 1" data-parent="">
        <form>
            <input name="address" value="Abbey Road 1">
            <input name="country" value="UK">
        </form>
    </li>
    <li data-node="Child 1" data-parent="Root 1">
        <form>
            <input name="address" value="Champs-Elysées 9">
            <input name="country" value="FR">
        </form>
    </li>
    <li data-node="Child 1 1" data-parent="Child 1">
        <form>
            <input name="address" value="Downing Street 10">
            <input name="country" value="UK">
        </form>
    </li>
    <li data-node="Child 2" data-parent="Root 1">
        <form>
            <input name="address" value="Wall Street 1">
            <input name="country" value="US">
        </form>
    </li>
</ul>

2. With additional data- attributes

If the extra data is not present in the form, but become additional data- attributes to the li elements (that was not clear to me), then it is similar:

function collectTree(ul) {
    // Create the nodes & identify the root
    let nodes = {};
    let root = null;
    for (let li of ul.children) {
        // Extract form data using the FormData API
        ({ node, parent, ...formdata} = li.dataset);
        nodes[node] = { formdata };
        if (!parent) root = nodes[node];
    }
    // Populate the children arrays
    for (let li of ul.children) {
        if (!li.dataset.parent) continue;
        let p = nodes[li.dataset.parent];
        if (!p.children) p.children = {};
        p.children[li.dataset.node] = nodes[li.dataset.node];
    }
    return root;
}

const root = collectTree(document.querySelector("ul"));

console.log(root);
<ul>
    <li data-node="Root 1" data-parent="" data-address="Abbey Road 1" data-country="UK"></li>
    <li data-node="Child 1" data-parent="Root 1" data-address="Champs-Elysées 9" data-country="FR"></li>
    <li data-node="Child 1 1" data-parent="Child 1" data-address="Downing Street 10" data-country="UK"></li>
    <li data-node="Child 2" data-parent="Root 1" data-address="Wall Street 1" data-country="US"></li>
</ul>

Sign up to request clarification or add additional context in comments.

1 Comment

This works perfectly, although for one top level root, which is exactly the scenario in my case. I was trying for multiple top level roots, just in case I need to modify it later. My form data isn't exactly like this, it's a complex form with multiple conditions, however I was able to adapt it accordingly. Thank you. I was thinking in terms of recursion, however I was going down a branch, and wasn't able to figure out how to get back to the parent, to continue traversing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.