1

I am making dynamic menus using a recursive function and I have already made the menus and it display in the right order without any issues.

Requirement:

Here I am in the need to find out the last level of menus and need to assign checkbox with value as their respective id {item.id}.

Eg:

For First menu one,

 -> [Checkbox with value as 1.1.1] One-One-One
 -> [Checkbox with value as 1.1.2] One - one - two
 -> [Checkbox with value as 1.1.3] One - one - three

For Second menu two,

 -> [Checkbox with value as 2.1] Two - one

.

.

.

For sixth menu six,

 -> [Checkbox with value as 6] Six

I hope the point is clear that I need to find out the last level children as like given above example and should assign a checkbox to it with the value of their id.

Please take a look at snippet provided below and help me to achieve the result of making the checkbox at the last level

Note: The checkbox have to be inline with the last level elements as like the example shown above with checkbox value as their respective id .

The purpose of this requirement is that it will have multiple submenus and the last level have the filter values so on click of the checkbox, I would pass the value to api and retrieve the related data for this particular checked menu item and will display.. But here I am in the need of checkbox display respective to menu item that's it..

const loadMenu = () => Promise.resolve([{id:"1",name:"One",children:[{id:"1.1",name:"One - one",children:[{id:"1.1.1",name:"One - one - one"},{id:"1.1.2",name:"One - one - two"},{id:"1.1.3",name:"One - one - three"}]}]},{id:"2",name:"Two",children:[{id:"2.1",name:"Two - one"}]},{id:"3",name:"Three",children:[{id:"3.1",name:"Three - one",children:[{id:"3.1.1",name:"Three - one - one",children:[{id:"3.1.1.1",name:"Three - one - one - one",children:[{id:"3.1.1.1.1",name:"Three - one - one - one - one"}]}]}]}]},{id:"4",name:"Four"},{id:"5",name:"Five",children:[{id:"5.1",name:"Five - one"},{id:"5.2",name:"Five - two"},{id:"5.3",name:"Five - three"},{id:"5.4",name:"Five - four"}]},{id:"6",name:"Six"}]);

const {Component, Fragment} = React;
const {Button, Collapse} = Reactstrap;

class Menu extends Component {
  constructor(props) {
    super(props);
    this.state = {menuItems: []};
  }

  render() {
    return <MenuItemContainer menuItems={this.state.menuItems} />;
  }

  componentDidMount() {
    loadMenu().then(menuItems => this.setState({menuItems}));
  }
}

function MenuItemContainer(props) {
  if (!props.menuItems.length) return null;
  
  const renderMenuItem = menuItem =>
    <li key={menuItem.id}><MenuItem {...menuItem} /></li>;
    
  return <ul>{props.menuItems.map(renderMenuItem)}</ul>;
}
MenuItemContainer.defaultProps = {menuItems: []};

class MenuItem extends Component {
  constructor(props) {
    super(props);
    this.state = {isOpen: false};
    this.toggle = this.toggle.bind(this);
  }

  render() {
    return (
      <Fragment>
        <Button onClick={this.toggle}>{this.props.name}</Button>
        <Collapse isOpen={this.state.isOpen}>
          <MenuItemContainer menuItems={this.props.children} />
        </Collapse>
      </Fragment>
    );
  }

  toggle() {
    this.setState(({isOpen}) => ({isOpen: !isOpen}));
  }
}

ReactDOM.render(<Menu />, document.getElementById("root"));
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/reactstrap/8.4.1/reactstrap.min.js"></script>

<div id="root"></div>
  • So you want checkbox for the last children, right? – Arun AK Mar 09 '20 at 23:59
  • @Thinker Yes in last level children alone.As like I mentioned in question.. If it is ```one```, then the checkbox needs to be placed for last level.. Three items here for ```one```.. ```One-One-One``` , ```One-One-Two```, ```One-One-Three``` .. Should have checkbox inline.. If it has only single element like ```Six``` then there should be checkbox for ```six``` alone.. –  Mar 10 '20 at 01:17
  • @Thinker, Could you please give me a right solution with th reference to the example snippet provided above.. –  Mar 10 '20 at 02:40

1 Answers1

0

From my understanding, you need checkbox for the last child. This can be achieved by checking whether the element has child or not.

Below are the changes that made in order to add the checkbox.

render() {
  
  let isLastChild = this.props.children ? false : true;
  
  return (
    <Fragment>
      <Button onClick={this.toggle}>{this.props.name}</Button>
      <Fragment>
        {isLastChild ? <Input type="checkbox" /> : ''}
      </Fragment>
      <Collapse isOpen={this.state.isOpen}>
        <MenuItemContainer menuItems={this.props.children} />
      </Collapse>
    </Fragment>
  );
}

Here is the plnkr link for your reference.

Hope it helps :)

Arun AK
  • 4,353
  • 2
  • 23
  • 46
  • Can you help me in this question please?? https://stackoverflow.com/questions/60616336/open-the-collapsible-menu-by-default-based-on-the-id –  Mar 10 '20 at 12:28