EaBengaluru
EaBengaluru

Reputation: 71

How to construct tree structure with details tags in javascript

i'm facing problem to construct a tree structure with details tag in javascript

my expected tree structure

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

with details tag i'm not able to get the desired structure which like below one

My expected result(when expanded or collapsed):

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

Note: i want to get desired structure with <details> tag only

Here is what i have tried:

Question: i want to get proper nesting structure with <details> tag(s)

var treeList = [
{
    "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"
}
];

var getTreeStrucureList = dataset => {
    var hashTable = Object.create(null);
   dataset.forEach(function(aData){
       hashTable[aData.id] = {...aData, childNodes: []};
    });
    var dataTree = [];
    dataset.forEach(aData => {
      
      if(aData.parentId) { hashTable[aData.parentId].childNodes.push(hashTable[aData.id]);}
      else { dataTree.push(hashTable[aData.id]); }
  
     // console.log(ul);
    });
    //console.log(dataTree);
    return dataTree;
  };
  
  
  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.childNodes || [])
      // Build the current item and add any nested lists
     return `<summary >
              ${item.name}
           </summary>${ 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 `<details>${ getListItems(dataset) }</details>`
    } else {
      return '';
    }
  };


    var nestedTreeList = getTreeStrucureList(treeList);   
    
    //console.log('tree list ',nestedTreeList);

   $('#tree').append(getTreeStrucureTemplate(nestedTreeList));
#tree{
   background: yellow;
   //height:50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>



<div id="tree"></div>



<p>Expected tree should look like below one(Above tree structure is different)</p>


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

Upvotes: 0

Views: 581

Answers (1)

Ben Stephens
Ben Stephens

Reputation: 3371

I've taken this to mainly be an HTML question rather than a JS one. Your code seems to produce a block of HTML like:

<details>
    <summary>Root</summary>
    <details>
        <summary>First Level item 1</summary>
        <summary>First Level item 2</summary>
        <details>
            <summary>second Level item 1</summary>
        </details>
    </details>
</details>

From looking at https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details it's probably not valid to have more than one summary element per details element, so perhaps it would be worth trying something like:

details > details {
  padding-left: 10px;
}

details span::before {
  content: "*";
  padding-right: 10px;
  padding-left: 10px;
}
<details>
  <summary>Root</summary>
  <span>First Level item 1</span>
  <details>
    <summary>First Level item 2</summary>
    <details>
      <summary>second Level item 1</summary>
    </details>
  </details>
</details>

Edit: worth noting the "First Level item 1" has been moved out of the second details element.

Upvotes: 1

Related Questions