2

I have build a sidebar with 3 level dropdown with using Material UI "List" where I am facing issue with 3rd level dropdown all child open together when I click on any of 2nd level dropdown. I am sharing the 2nd and 3rd level code samples where I want to manage the dropdown onClick event work individually on 2nd dropdown list.

I want solution for Individual onClick on second level dropdown. where the third level open to related onClick event.

{
      id: 'finance-management',
      icon: <img src="/images/finance-mgt.svg" />,
      name: 'Finance Management',
      url: 'finance',
      dropDown: [
        { 
        id: "profit",  
        sublist: "Profit & Loss",
          superSubList: [
            { superlist: "Payments"},
            { superlist: "Receivables"},
            { superlist: "Cashflow"},
            { superlist: "Profit & Loss Statement"},
          ]
      },
      { 
        id: "suppliers", 
        sublist: "Suppliers",
          superSubList: [
            { superlist: "Overview"},
            { superlist: "Create New"}
          ]
        }
      ]
     },
----------------------------------------------------

 const [sublistcl, setSubListcl] = useState();
   
  const handleSubClick = () => {
    setSubListcl(!sublistcl)
  };
----------------------------------------------------

{menuItem?.dropDown?.map((menuSubItem) => (
                    <div className="sub-drop-down">
                      <Collapse in={open} >
                      <List component="div" disablePadding>
                        <ListItemButton sx={{ pl: 4 }}
                        //  onClick={isExpandable && handleSubClick}
                         onClick={handleSubClick}
                         key={menuSubItem.id}
                        >
                          <ListItemText primary={menuSubItem.sublist} />
                          {sublistcl ? <ExpandLess /> : <ExpandMore />}
                          {/* {sublistcl  && !sublistcl && <ExpandMore />}
                          {sublistcl  && sublistcl && <ExpandLess />} */}
                        </ListItemButton>
                        {/* Super Sub List Item */}
                        
                           {menuSubItem?.superSubList?.map((itemThird) =>(
                             
                            <div className="list-item-subchild">
                            
                             <Collapse in={sublistcl} >
                                <List component="div" disablePadding>
                                <ListItemButton sx={{ pl: 5 }}>
                                  <ListItemText primary={itemThird.superlist} />
                                </ListItemButton>
                                </List>
                                </Collapse>
                               
                            </div>  
                           ))}
                      </List>
                    </Collapse>
                    </div> 
                  ))}

-----------------------------------------------
Rita Mehra
  • 21
  • 1

1 Answers1

1

The code sample in the question uses the object shapes for the menu options as shown below. These object shapes make it difficult to reuse the same code to process menu options from any level in the hierarchy. They also make it difficult to uniquely identify each object. Some suggestions for improvement are below.

FirstLevelMenuOption object shape

interface FirstLevelMenuOption {
    id       : string,
    icon     : JSXElement,
    name     : string
    url      : string
    dropDown : SecondLevelMenuOption[]
}

SecondLevelMenuOption object shape

interface SecondLevelMenuOption {
    id           : string,
    sublist      : string
    superSubList : ThirdLevelMenuOption[]
}

ThirdLevelMenuOption object shape

interface ThirdLevelMenuOption {
    superlist : string
}

Suggestions:

  1. All three levels should have an id property that uniquely identifies the object instance.
  2. The object instance selected by the user for expansion (or collapse) should be represented by the object's id property.
  3. The expanded/collapsed state of a menu option needs to be captured independently for each menu option rather than using a single open/closed state value for the entire menu.
  4. Menu options from all hierarchical levels should have the same object shape with the same property names if possible.
  5. The raw data structure of the objects should represent their hierarchical relationship using object properties (e.g. a parentId property), rather than a hard-coded multi-level structure of the object tree. Object trees can be built from the raw data structure.
  6. The Material-UI Tree View is well-suited to represent hierarchies with collapsible sub-levels, and could be used to solve the problem presented by the question (see Demo below).

Demo

A live demo with an expandable MUI Drawer demonstrates using the MUI documentation's Controlled tree view and ContentComponent prop examples. In the demo, click the navigation menu icon to open the drawer. A code repository for the demo is available.

The demo uses the object shape below for all options at all levels. Note that the icon property is now a string for the icon src attribute rather than a JSXElement. The JSXElement can be created from the src attribute by the code that loops over each menu option (this is not shown in the demo's code).

interface MenuOption {
    id       : string,
    icon     : string,
    name     : string,
    url      : string,
    subList  : MenuOption[]
}
kofeigen
  • 1,331
  • 4
  • 8