1

I have a complex JSON Object that needs to be grouped by parentId. So far I achieved my desired output within this code:

// My JSON Data
const locations = [
  {
    id: 1,
    name: "San Francisco Bay Area",
    parentId: null
  },
  {
    id: 2,
    name: "San Jose",
    parentId: 3
  },
  {
    id: 3,
    name: "South Bay",
    parentId: 1
  },
  {
    id: 4,
    name: "San Francisco",
    parentId: 1
  },
  {
    id: 5,
    name: "Manhattan",
    parentId: 6
  },
];
function createTreeView(location) {
  var tree = [],
    object = {},
    parent,
    child;

  for (var i = 0; i < location.length; i++) {
    parent = location[i];

    object[parent.id] = parent;
    object[parent.id]["children"] = [];
  }

  for (var id in object) {
    if (object.hasOwnProperty(id)) {
      child = object[id];

      if (child.parentId) {
        object[child["parentId"]]["children"].push(child);
      } else {
        tree.push(child);
      }
    }
  }
  return tree;
}

I am only displaying it as plain JSON Data using

var root = createTreeView(locations);
document.body.innerHTML = "<pre>" + JSON.stringify(root, null, " ");

Is there any possible to put this JSON data inside the <li> using the code above

3
  • Can you show a sample of what the final html you want, should look like? Commented Jun 21, 2019 at 8:04
  • 2
    So you want to display your tree as nested <ul> and <li> elements? It's not clear enough what is the problem. BTW, I tried using your createTreeView function with the given locations array and it threw an error. Commented Jun 21, 2019 at 8:07
  • @nickzoum Here is the sample HTML that I want to achieve: <imgur.com/31mHGl6> Commented Jun 21, 2019 at 8:19

2 Answers 2

3

Here, i made an example. Have a look at CreateUlTreeView and make sure you read the comment.

// My JSON Data
const locations = [
  {
    id: 1,
    name: "San Francisco Bay Area",
    parentId: null
  },
  {
    id: 2,
    name: "San Jose",
    parentId: 3
  },
  {
    id: 3,
    name: "South Bay",
    parentId: 1
  },
  {
    id: 4,
    name: "San Francisco",
    parentId: 1
  },
  {
    id: 5,
    name: "Manhattan",
    parentId: 6
  },
];
function createTreeView(location) {
  var tree = [],
    object = {},
    parent,
    child;

  for (var i = 0; i < location.length; i++) {
    parent = location[i];

    object[parent.id] = parent;
    object[parent.id]["children"] = [];
  }

  for (var id in object) {
    if (object.hasOwnProperty(id)) {
      child = object[id];
      // i made some changes here incase some element is missing so you dont get error and just append th tree insetad 
      if (child.parentId && object[child["parentId"]]) {
        object[child["parentId"]]["children"].push(child);
      } else {
        tree.push(child);
      }
    }
  }
  return tree;
}


// here is how you build your UL treeview recursively
function CreateUlTreeView(items, parent){
var ul = document.createElement("ul");
if (parent)
    parent.appendChild(ul);
    items.forEach(function(x) {
      var li = document.createElement("li");
      var text = document.createElement("span");
      text.innerHTML = x.name;
      li.appendChild(text);
      if (x.children && x.children.length>0)
         CreateUlTreeView(x.children, li);
      ul.append(li);
    });
    return ul;
}
var root = createTreeView(locations);

CreateUlTreeView(root,document.getElementById("container"))
<div id="container">

</div>

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

Comments

1

This is a pretty abstract solution. That you can reuse fairly easily.

The part that triggers the whole tree is:

// <LIST>.toTree(<FUNCTION TO GET ID>, <FUNCTION TO GET PARENT ID>);
var tree = locations.toTree(location => location.id, location => location.parentId);
// createTreeView(<TREE>, <FUNCTION TO GET NAME>);
document.body.appendChild(createTreeView(tree, location => location.name)).id = "myUL";

Object.defineProperty(Array.prototype, "toTree", {
  configurable: false,
  writable: false,
  value: function(getKey, getParentKey) {
    var list = JSON.parse(JSON.stringify(this));
    var root = {};
    for (var index = 0; index < list.length; index++) {
      var parentKey = getParentKey.call(list, list[index], index, list);
      var parent = (list.find(function(item, index) {
        return parentKey === getKey.call(list, item, index, list);
      }) || root);
      (parent.children = parent.children || []).push(list[index]);
    }
    return root.children || [];
  }
});

const locations = [{
  id: 1,
  name: "San Francisco Bay Area",
  parentId: null
}, {
  id: 2,
  name: "San Jose",
  parentId: 3
}, {
  id: 3,
  name: "South Bay",
  parentId: 1
}, {
  id: 4,
  name: "San Francisco",
  parentId: 1
}, {
  id: 5,
  name: "Manhattan",
  parentId: 6
}, ];

function createTreeView(tree, getName) {
  var listDom = document.createElement("ul");
  tree.forEach(function(item) {
    var itemDom = listDom.appendChild(document.createElement("li"));
    if (item.children && item.children.length) {
      var itemName = itemDom.appendChild(document.createElement("span"));
      itemName.textContent = getName.call(item, item);
      itemName.className = "caret";
      var nestedList = itemDom.appendChild(createTreeView(item.children, getName));
      nestedList.className = "nested";
    } else {
      itemDom.textContent = getName.call(item, item);
    }
  });
  return listDom;
}

var tree = locations.toTree(location => location.id, location => location.parentId);
document.body.appendChild(createTreeView(tree, location => location.name)).id = "myUL";

Comments

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.