0

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>

3
  • Your first and second blocks of code are the same, is that intentional? You seem to be missing a </ul> in the code blocks. Commented Feb 9, 2021 at 8:19
  • @BenStephens i'm not asking about <ul><li> . my question is i want to wrap structure properly with <details> tag Commented Feb 9, 2021 at 8:36
  • Have you tried using document.createElement() and document.appendChild() ? You should be able to create any HTML text you want, add it into a tag of your choice using let yourDataStructureAsANode = document.createElement("sometag").innerHTML = "your HTML string here"; and then simply document.body.appendChild(document.createElement("details").appendChild(yourDataStructureAsANode)); Although keep in mind that you may have to divide that statement into several lines since return types might be mixed up. However that should be the general idea. Commented Feb 9, 2021 at 8:43

1 Answer 1

1

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.

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

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.