0

I wanted to make nested list so that it resembles tree folder structure

Here is how i'm expecting my list

I want any number of nested list

here is what i have tried but not working

    <link href="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.css" rel="stylesheet">
    
    
    <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
    
       <script src="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.js"></script>
       
       
      <ul class="mdc-list" style="margin-left: 17px;padding: 0;margin-top: -7px;">
                <li class="mdc-list-item" tabindex="0">
                    <span class="material-icons"> arrow_right </span>
                    <span class="mdc-list-item__ripple"></span><span class="material-icons folder-base-color"> folder </span>
                    
                    <span class="mdc-list-item__text">json-dumps</span>
                </li>
                    
                  <li class="mdc-list-item" tabindex="0">
                    <span class="material-icons"> arrow_right </span>
                    <span class="mdc-list-item__ripple"></span><span class="material-icons folder-base-color"> folder </span>
                    
                    <span class="mdc-list-item__text">test</span>


                    <ul class="mdc-list" style="margin-left: 17px;padding: 0;margin-top: -7px;">
                      <li class="mdc-list-item" tabindex="0">
                          <span class="material-icons"> arrow_right </span>
                          <span class="mdc-list-item__ripple"></span><span class="material-icons folder-base-color"> folder </span>
                          
                          <span class="mdc-list-item__text">nested test</span>
                      </li>
                          
                          <li class="mdc-list-item" tabindex="0">
                          <span class="material-icons"> arrow_right </span>
                          <span class="mdc-list-item__ripple"></span><span class="material-icons folder-base-color"> folder </span>
                          
                          <span class="mdc-list-item__text">nested test 2</span>
                      </li>
                    </ul>

                </li>
           </ul>
Spatz
  • 18,640
  • 7
  • 62
  • 66
Learner
  • 61
  • 2
  • 21
  • Still I didn't get the solution please help me thanks in advance!! – Learner Feb 07 '21 at 17:38
  • without js code i meant for structure that can be hardcoded for any nested level – Learner Feb 08 '21 at 09:33
  • IMHO you are trying to misuse mdc-list component. Take a look at [design guidelines for the list component](https://material.io/components/lists#types). It is not supposed to be used as tree view. It may have only one sublevel, while you need many sublevels. I think you need to use specialized tree view component instead. – Konstantin Lyakh Feb 09 '21 at 19:50

2 Answers2

2

Edit: I have updated the code sandbox link to use ul and li

See if this works for you https://codesandbox.io/s/stupefied-swirles-219nc?file=/index.html

It gives your the functionality as well without JS, like you asked.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Static Template</title>
    <style>
      .app-nested-nav__section-content {
        margin-left: 2em;
      }
    </style>
  </head>
  <body>
    <link
      href="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.css"
      rel="stylesheet"
    />

    <link
      rel="stylesheet"
      href="https://fonts.googleapis.com/icon?family=Material+Icons"
    />

    <script src="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.js"></script>

    <details class="app-nested-nav__section" open>
      <summary class="app-nested-nav__section-header mdc-list-item">
        <span class="mdc-list-item__ripple"></span
        ><span class="material-icons folder-base-color"> folder </span>

        <span class="mdc-list-item__text">json-dumps</span></summary
      >
      <details class="app-nested-nav__section-content">
        <summary class="app-nested-nav__section-header mdc-list-item">
          <span class="mdc-list-item__ripple"></span
          ><span class="material-icons folder-base-color"> folder </span>

          <span class="mdc-list-item__text">json-dumps</span></summary
        >
        <div class="app-nested-nav__section-content">
          <summary class="app-nested-nav__section-header mdc-list-item">
            <span class="mdc-list-item__ripple"></span
            ><span class="material-icons folder-base-color"> folder </span>

            <span class="mdc-list-item__text">json-dumps</span></summary
          >
          <summary class="app-nested-nav__section-header mdc-list-item">
            <span class="mdc-list-item__ripple"></span
            ><span class="material-icons folder-base-color"> folder </span>

            <span class="mdc-list-item__text">json-dumps</span></summary
          >
          <summary class="app-nested-nav__section-header mdc-list-item">
            <span class="mdc-list-item__ripple"></span
            ><span class="material-icons folder-base-color"> folder </span>

            <span class="mdc-list-item__text">json-dumps</span></summary
          >
        </div>
      </details>
      <summary class="app-nested-nav__section-content mdc-list-item">
        <span class="mdc-list-item__ripple"></span
        ><span class="material-icons folder-base-color"> folder </span>

        <span class="mdc-list-item__text">json-dumps</span></summary
      >
    </details>
  </body>
</html>

Inspired by https://codepen.io/rustemgareev/pen/GOBado

Rohith Balaji
  • 848
  • 7
  • 21
1

You could try something like the following example. All the elements are created based on the elements provided in the JSON, the recursive function buildTree and a <template> element. The schema of the JSON is quite simple (title,iconClass,children). I think you will find it very simple.

const buildTree = (tree, ancestor = null) => {
  let ulMDCList = document.querySelector('.mdc-list');
  tree.forEach((item, index) => {
    let liTemplate = document.getElementById('list-item').content.cloneNode(true);
    let liMDCItem = liTemplate.querySelector('.mdc-list-item');    
    
    if(ancestor !== null) {
      liMDCItem.dataset.childOf = ancestor.id;
      liMDCItem.classList.add('child','hidden'); 
      liMDCItem.id = ancestor.id + liMDCItem.dataset.id + index;
      liMDCItem.dataset.z = parseInt(ancestor.dataset.z) + 1;
    } else {
      liMDCItem.id = liMDCItem.dataset.id + index;
      liMDCItem.dataset.z = 0;
    }
    let arrow = liTemplate.querySelector('span[data-id="arrow"]');
    let icon = liTemplate.querySelector('span[data-id="icon"]');
    let title = liTemplate.querySelector('span[data-id="title"]');    
    if(item.iconClass.length > 0) {  
      icon.innerHTML = item.iconClass;
    }
    title.innerHTML = item.title;
    ulMDCList.append(liTemplate);
    if(hasChildren(item.children)) {
      buildTree(item.children, liMDCItem);
      liMDCItem.addEventListener('click', (e) => {
        if(arrow.innerHTML == 'arrow_drop_down') {
          arrow.innerHTML = 'arrow_right';
        } else {
          arrow.innerHTML = 'arrow_drop_down';
        }
        ulMDCList.querySelectorAll(`[data-child-of=\"${liMDCItem.id}\"]`).forEach((item) => { item.classList.toggle('hidden') });
      });     
    } else {
      arrow.innerHTML = '';
    }
  });
}
const hasChildren = (children) => {
  return (typeof children !== 'undefined' && Array.isArray(children) && children.length > 0);
}
const menuData = '[{"title": "json", "iconClass": "folder", "children": [{"title": "1st-child", "iconClass": "folder", "children": [{"title": "Another image", "iconClass": "image", "children": []},{"title": "Another folder", "iconClass": "folder", "children": [{"title": "And another image", "iconClass": "image", "children": []}]}]},{"title": "My image", "iconClass": "image", "children": []}]},{"title": "A solo image", "iconClass": "image", "children": []}]';
mdc.autoInit();
buildTree(JSON.parse(menuData));
.mdc-list-item.hidden {
 display: none;
}
[data-z="1"] {
  margin-left: 5%;
}
[data-z="2"] {
  margin-left: 10%;
}
[data-z="3"] {
  margin-left: 15%;
}

[data-id="icon"] {
  padding-right: 0.5rem;
  width: 1.25rem;
}
[data-id="arrow"] {
  width: 1.25rem;
}
.material-icons.image {
  content: 'image';
}
<link href="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.css" rel="stylesheet"/>
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<script src="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.js"></script>
<ul class="mdc-list" aria-role="list" aria-orientation="vertical">
</ul>

<template id="list-item">
  <li class="mdc-list-item" tabindex="0" data-id="listitem">
    <span class="material-icons" data-id="arrow"> arrow_right </span>
    <span class="mdc-list-item__ripple"></span>
    <span class="material-icons" data-id="icon"> folder </span>
    <span class="mdc-list-item__text" data-id="title"></span>
  </li>
</template>