最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Create a nested list from a object - Stack Overflow

programmeradmin1浏览0评论

I have the following object

var json = {
    items:[
        {id:45 , lable:"Test 1.2.1", parent_id: 2},
        {id:12, lable:"Test 1.0", parent_id: 0},
        {id:32, lable:"Test 1.1", parent_id: 12},
        {id:2, lable:"Test 1.2", parent_id: 12}
    ]
}

Using this object i needed to create a nested list, which will look like the following in the browser

  • Test 1.0
    • Test 1.1
    • Test 1.2
      • Test 1.2.1

My approach was to write a function that would go through the object and store the values in the array of list of elements

function appendItems(json){
    var list = json.items;
    var listelem = [];

    list.forEach(function(i){
        var listelements = document.createElement('li');
        listelements.setAttribute("id",i.id);
        listelements.setAttribute("data-parent-id", i.parent_id);
        listelements.innerText = i.lable;
        listelem.push(listelements);

    })

    console.log(listelem);    
}

But i am unsure of how to get that nested structure from this point

I have the following object

var json = {
    items:[
        {id:45 , lable:"Test 1.2.1", parent_id: 2},
        {id:12, lable:"Test 1.0", parent_id: 0},
        {id:32, lable:"Test 1.1", parent_id: 12},
        {id:2, lable:"Test 1.2", parent_id: 12}
    ]
}

Using this object i needed to create a nested list, which will look like the following in the browser

  • Test 1.0
    • Test 1.1
    • Test 1.2
      • Test 1.2.1

My approach was to write a function that would go through the object and store the values in the array of list of elements

function appendItems(json){
    var list = json.items;
    var listelem = [];

    list.forEach(function(i){
        var listelements = document.createElement('li');
        listelements.setAttribute("id",i.id);
        listelements.setAttribute("data-parent-id", i.parent_id);
        listelements.innerText = i.lable;
        listelem.push(listelements);

    })

    console.log(listelem);    
}

But i am unsure of how to get that nested structure from this point

Share Improve this question edited Nov 4, 2015 at 20:27 Matt Burland 45.2k18 gold badges107 silver badges179 bronze badges asked Nov 4, 2015 at 20:23 RRPRRP 2,8539 gold badges32 silver badges55 bronze badges 4
  • Are you open to look at plugins like jsTree? If not it will need recursion. – ndd Commented Nov 4, 2015 at 20:35
  • no plugins trying to achieve this via pure js – RRP Commented Nov 4, 2015 at 20:35
  • So no to jquery too, right? – ndd Commented Nov 4, 2015 at 20:36
  • @ndd right no jquery – RRP Commented Nov 4, 2015 at 20:41
Add a ment  | 

2 Answers 2

Reset to default 9

I would start by transforming you array into an actual tree. You could do it like this:

var obj = {
    items:[
        {id:45 , lable:"Test 1.2.1", parent_id: 2},
        {id:12, lable:"Test 1.0", parent_id: 0},
        {id:32, lable:"Test 1.1", parent_id: 12},
        {id:2, lable:"Test 1.2", parent_id: 12}
    ]
}

// first we create a dictionary so we can find elements by id easily
var objDict = obj.items.reduce(function(p,c) {
    p[c.id] = c;
    c.children = [];
    return p;
}, {});

// then we build our tree
var tree = obj.items.reduce(function(p,c) {
    // if the parent_id is zero, we have found the root.
    if (!c.parent_id) {
        p = c;
    }
    // otherwise, figure out who the parent is and add this one as a child
    else {
        objDict[c.parent_id].children.push(c);
    }
    return p;
}, {});

console.log(JSON.stringify(tree));

This would give you an object that looks like this:

{
    "id": 12,
    "lable": "Test 1.0",
    "parent_id": 0,
    "children": [
        {
            "id": 32,
            "lable": "Test 1.1",
            "parent_id": 12,
            "children": []
        },
        {
            "id": 2,
            "lable": "Test 1.2",
            "parent_id": 12,
            "children": [
                {
                    "id": 45,
                    "lable": "Test 1.2.1",
                    "parent_id": 2,
                    "children": []
                }
            ]
        }
    ]
}

Which should now be easy for you to process. Start with the root and create a node, then do a depth first search down each child making nested nodes as needed.

Something like this:

processTree(tree, document.getElementById("list"));

function processTree(node, element) {
    var li = document.createElement('li');
    li.innerText = node.lable;
    element.appendChild(li);
    if (node.children.length) {
        var ul = document.createElement('ul');
        li.appendChild(ul);
        // note: you might want / need to actual sort the children first
        // but it's not clear from the OP if sorting by id will always give the right order
        for (var i=0; i < node.children.length; i++) {
           processTree(node.children[i], ul);
        }
    }
}

To give you a working example like this:

var obj = {
  items: [{
    id: 45,
    lable: "Test 1.2.1",
    parent_id: 2
  }, {
    id: 12,
    lable: "Test 1.0",
    parent_id: 0
  }, {
    id: 32,
    lable: "Test 1.1",
    parent_id: 12
  }, {
    id: 2,
    lable: "Test 1.2",
    parent_id: 12
  }]
}

var objDict = obj.items.reduce(function(p, c) {
  p[c.id] = c;
  c.children = [];
  return p;
}, {});

var tree = obj.items.reduce(function(p, c) {
  if (!c.parent_id) {
    p = c;
  } else {
    objDict[c.parent_id].children.push(c);
  }
  return p;
}, {});

processTree(tree, document.getElementById("list"));

function processTree(node, element) {
  var li = document.createElement('li');
  li.innerText = node.lable;
  element.appendChild(li);
  if (node.children.length) {
    var ul = document.createElement('ul');
    li.appendChild(ul);
    for (var i = 0; i < node.children.length; i++) {
      processTree(node.children[i], ul);
    }
  }
}
<ul id="list">
</ul>

Here's a simple solution using recursion. I've used a helper function that returns an array of the children for a given parent_id. I hope you find it helpful.

'use strict';

(function() {

    function childrenOf(targetId, items) {
        var children = [];
        items.forEach(function(item) {
            if (item.parent_id === targetId) {
                children.push(item);
            }
        });
        return children;
    }

    function nestedList(id, items) {
        var result = '';
        var children = childrenOf(id, items);
        if (children.length) {
            result = '<ul>';
            children.forEach(function(child) {
                result += '<li>';
                result += child.label;
                result += nestedList(child.id,items);
                result += '</li>';
            });
            result += '</ul>';
        }
        return result;
    }

    var json = {
        items:[
            {id:45 , label:"Test 1.2.1", parent_id: 2},
            {id:12, label:"Test 1.0", parent_id: 0},
            {id:32, label:"Test 1.1", parent_id: 12},
            {id:2, label:"Test 1.2", parent_id: 12}
        ]
    }

    var rootId = 0;
    var output = nestedList(rootId, json.items);
    console.log('<html><body>');
    console.log(output);
    console.log('</body></html>');



})();

It produces the following output:

<html>

<body>
    <ul>
        <li>Test 1.0
            <ul>
                <li>Test 1.1</li>
                <li>Test 1.2
                    <ul>
                        <li>Test 1.2.1</li>
                    </ul>
                </li>
            </ul>
        </li>
    </ul>
</body>

</html>
发布评论

评论列表(0)

  1. 暂无评论