简体   繁体   中英

How to get html nested structure with ul, li for a tree data array

Hi i want to get nested tree structure based on nesting

Something like this

<ul> 
   <li>Root 
      <ul>
        <li>First level item 1</li>
        <li>
          First level item 2
            <ul>
               <li>second level item1</li>
            </ul>
        </li>
     </ul>
</li>

Question: my function is not returning tree structure markup properly.

Note: i don't want to add 1 more loop

Here is what i have tried:

 var getTreeStrucureTemplate = dataset => { var hashTable = Object.create(null), ul = '',li = ''; dataset.forEach(function(aData){ hashTable[aData.id] = {...aData, childNodes: []}; ul = '<ul>'; }); var dataTree = []; dataset.forEach(aData => { if(aData.parentId) { hashTable[aData.parentId].childNodes.push(hashTable[aData.id]); ul += '<li>'+aData.name+'</li>';} else { dataTree.push(hashTable[aData.id]); ul += '</ul><ul>' } // console.log(ul); }); //console.log(dataTree); var treeStructure = ul; return treeStructure; }; var list = [ { "parentId": 0, "id": 1, "name": "Root" }, { "parentId": 1, "id": 2, "name": "First Level item 1" }, { "parentId": 1, "id": 3, "name": "First Level item 2" }, { "parentId": 3, "id": 4, "name": "second Level item 1" } ]; console.log(getTreeStrucureTemplate(list))

This is how I would go about this:

  • Use a nested data structure with each object containing it's children
  • Use a set of recursive functions that call each other to automatically deal with any number of layers

(It only runs as many times as needed, but whether your consider recursive functions as loops is up to you)

 var getListItems = dataset => { // Create a string containing the items for this list return dataset.map(item => { // Build a nested UL string by calling getTreeStrucureTemplate on this objects children var nested = getTreeStrucureTemplate(item.children || []) // Build the current item and add any nested lists return `<li>${ item.name }</li>${ nested }` }).join('') // Join the items into a single string } var getTreeStrucureTemplate = dataset => { // Only wrap the list in UL if it has contents if (dataset.length) { return `<ul>${ getListItems(dataset) }</ul>` } else { return '' } }; var list = [{ "name": "A", "children": [{ "name": "B", "children": [{ "name": "C" }, { "name": "D" }] }] }, { "name": "E", "children": [{ "name": "F" }] } ] var test = getTreeStrucureTemplate(list) document.getElementById('test').innerHTML = test console.log(test)
 <div id="test"></div>

I tried to work with the structure that you have given here in your question. I don't really understand where you don't want to use another loop, but here is my suggestion to resolve your problem.

var getTreeStrucureTemplate = dataset => {
  var hashTable = {}, ul = '',li = '';
    var dataTree = [];
    
    dataset.forEach(item => {
         if (item.parentId) {
            if (hashTable[item.parentId]) {
                hashTable[item.parentId].childNodes.push(item);
            } else {
                hashTable[item.parentId] = {id: item.patentId, childNodes: [item]};         
            }
         } else {
            hashTable[item.id] = {...item, childNodes: []};
         }
  });
    
    console.log('-=-=-=-=-=-=-=-=-=-=-=-=-=-');
    console.log(hashTable)
    console.log('-=-=-=-=-=-=-=-=-=-=-=-=-=-');
  

    Object.values(hashTable).forEach(node => {
        ul += '<ul>' + node.name;
        node.childNodes.forEach(subNode => {
            ul += '<li>' + subNode.name + '</li>';
        });
        ul += '</ul>';
    })
  
  return ul;
};

var list = [
    {
        "parentId": 0,
        "id": 1,
        "name": "First Level"
    },
    {
        "parentId": 1,
        "id": 2,
        "name": "First Level item 1"
    },
    {
        "parentId": 0,
        "id": 3,
        "name": "First Level 2"
    },
    {
        "parentId": 3,
        "id": 4,
        "name": "First Level 2 item 1"
    }
];


console.log(getTreeStrucureTemplate(list))

I am printing the array after it is reformatted to the desired way. I think you can improve this code in terms of performance if you see fit, but the way it is written here should be pretty clear about what we are trying to accomplish.

I hope it would help.

updated version to support as many nested levels as you would like:

var getTreeStrucureTemplate = dataset => {
  var hashTable = {}, ul = '',li = '';
    var dataTree = [];
    
    dataset.forEach(item => {
        if (item.parentId) {
            if (hashTable[item.parentId]) {
                hashTable[item.parentId].childNodes.push(item);
            } else {
                hashTable[item.parentId] = {id: item.patentId, childNodes: [item]};         
            }
        } else {
            hashTable[item.id] = {...item, childNodes: []};
        }
  });
    
    console.log('-=-=-=-=-=-=-=-=-=-=-=-=-=-');
    console.log(hashTable)
    console.log('-=-=-=-=-=-=-=-=-=-=-=-=-=-');
  

    Object.values(hashTable).forEach(node => {
        ul += createSubTree(node);
    })
  
  return ul;
};

var createSubTree = tree => {
    var str = '';
    str += '<ul>' + tree.name;
    tree.childNodes.forEach(subNode => {
        str += '<li>' + subNode.name + '</li>';
        if (subNode.childNodes && subNode.childNodes.length) {
            str += createSubTree(subNode.childNodes);
        }
    });
    str += '</ul>';

    return str;
}

var list = [
    {
        "parentId": 0,
        "id": 1,
        "name": "First Level"
    },
    {
        "parentId": 1,
        "id": 2,
        "name": "First Level item 1"
    },
    {
        "parentId": 0,
        "id": 3,
        "name": "First Level 2"
    },
    {
        "parentId": 3,
        "id": 4,
        "name": "First Level 2 item 1"
    }
];


console.log(getTreeStrucureTemplate(list))

is that what you are looking for?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM