0

I am trying to turn the json data that is in the db variable into a nested list on the html page. Instead it is giving me a sort of ladder of each child node inserted into the child node before it. I can not figure out why it is not nesting correctly. What am i missing?

db = JSON.parse(`
                {
                    "title": "Root", 
                    "children": [
                        {
                            "title": "Child1",
                            "children": [
                                {"title": "Child1a"},
                                {"title": "Child1b"},
                                {"title": "Child1c"}
                            ]
                        },
                        {
                            "title": "Child2",
                            "children": [
                                {"title": "Child2a"},
                                {"title": "Child2b"},
                                {"title": "Child2c"}
                            ]
                        }
                    ]
                }
            `);

function recurse(u, j) {

  li = document.createElement('li');
  ul = document.createElement('ul');

  li.setAttribute('title', j.title);

  li.appendChild(ul);
  u.appendChild(li);

  (j.children || []).forEach(c => {
    recurse(ul, c);
  });

}

recurse(document.getElementById('tree'), db);
* {
  margin: 0;
}

li::before {
  content: attr(title);
}

li:hover {
  cursor: grab;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <title>Scratch</title>
</head>

<body>
  <ul id='tree'></ul>
</body>

</html>
Barmar
  • 741,623
  • 53
  • 500
  • 612
eleethesontai
  • 454
  • 5
  • 19
  • 4
    Declare your variables local to the function with `let`. – Barmar Nov 23 '21 at 20:06
  • Otherwise they're global variables, and when you recurse you overwrite the variables used in the caller. – Barmar Nov 23 '21 at 20:06
  • 2
    *Always* declare your variables. – Barmar Nov 23 '21 at 20:07
  • wow thank you! I was not aware that javascript did this. – eleethesontai Nov 23 '21 at 20:08
  • 1
    @pilchard It's not a typo. But reproducible and exemplary :) – Gleb Kemarsky Nov 23 '21 at 20:15
  • @GlebKemarsky That's fair, but then should be closed as duplicate for any of the myriad `scope` questions including [What is the purpose of the var keyword and when should I use it (or omit it)?](https://stackoverflow.com/questions/1470488/what-is-the-purpose-of-the-var-keyword-and-when-should-i-use-it-or-omit-it) – pilchard Nov 23 '21 at 21:11
  • @pilchard The same fix can solve many problems. And many problems can be based on a common mistake. But the "duplicated question", in my opinion, is more related to describing the problematic behavior when working on a specific task. You can clarify this point by asking a question on https://meta.stackoverflow.com/ – Gleb Kemarsky Nov 24 '21 at 07:14

1 Answers1

2

You're referring to the same variables over and over because you're not re-declaring them in the function scope.

db = JSON.parse(`
                {
                    "title": "Root", 
                    "children": [
                        {
                            "title": "Child1",
                            "children": [
                                {"title": "Child1a"},
                                {"title": "Child1b"},
                                {"title": "Child1c"}
                            ]
                        },
                        {
                            "title": "Child2",
                            "children": [
                                {"title": "Child2a"},
                                {"title": "Child2b"},
                                {"title": "Child2c"}
                            ]
                        }
                    ]
                }
            `);

function recurse(u, j) {

  var li = document.createElement('li');
  var ul = document.createElement('ul');

  li.setAttribute('title', j.title);

  li.appendChild(ul);
  u.appendChild(li);

  (j.children || []).forEach(c => {
    recurse(ul, c);
  });

}

recurse(document.getElementById('tree'), db);
* {
  margin: 0;
}

li::before {
  content: attr(title);
}

li:hover {
  cursor: grab;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <title>Scratch</title>
</head>

<body>
  <ul id='tree'></ul>
</body>

</html>
I wrestled a bear once.
  • 22,983
  • 19
  • 69
  • 116