Marc Francisco
Marc Francisco

Reputation: 43

How to populate list and create a Tree-View from JSON Object - JavaScript

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

Upvotes: 1

Views: 5744

Answers (2)

nick zoum
nick zoum

Reputation: 7305

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";

Upvotes: 1

Alen.Toma
Alen.Toma

Reputation: 4870

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>

Upvotes: 3

Related Questions