Nested menu (sub-menu)

前端 未结 2 534
野性不改
野性不改 2021-01-05 08:13

I\'m trying to implement Sub-menu (nested menu).

It\'s worth to mention that I\'m using hydra component and don\'t have previous experience with redux (started learn

相关标签:
2条回答
  • 2021-01-05 09:01

    I've searched the same question. But couldn't find a nested menu implementation. So I wrote my own. Check the code below;

    import React, { Component, createElement } from "react";
    import {
      Admin,
      Resource,
      Layout,
      MenuItemLink,
      getResources
    } from "react-admin";
    import jsonServerProvider from "ra-data-json-server";
    import { withRouter } from "react-router-dom";
    import { connect } from "react-redux";
    import {
      List,
      ListItem,
      Collapse,
      ListItemText,
      ListItemIcon
    } from "@material-ui/core";
    import { ExpandLess, ExpandMore, StarBorder, LabelIcon } from "@material-ui/icons";
    import { withStyles } from "@material-ui/core/styles";
    
    const menuStyles = theme => ({
      nested: {
        paddingLeft: theme.spacing.unit * 4
      }
    });
    
    class Menu extends Component {
      menuList = [
        { name: "A", label: "Top menu 1", icon: <LabelIcon /> },
        { name: "B", label: "Top menu 2", icon: <LabelIcon /> },
        { name: "c", label: "Top menu 3", icon: <LabelIcon /> }
      ];
      constructor(props) {
        super(props);
        this.state = { open: "A" };
      }
      render() {
        const { resources, onMenuClick, logout } = this.props;
        return (
          <div>
            <List component="nav">
              {this.menuList.map(menu => {
                return (
                  <div key={menu.name}>
                    <ListItem
                      button
                      onClick={() => this.setState(state => ({ open: menu.name }))}
                    >
                      <ListItemIcon>{menu.icon}</ListItemIcon>
                      <ListItemText inset primary={menu.label} />
                      {this.state.open == menu.name ? (
                        <ExpandLess />
                      ) : (
                        <ExpandMore />
                      )}
                    </ListItem>
                    <Collapse
                      in={this.state.open == menu.name}
                      timeout="auto"
                      unmountOnExit
                    >
                      <List component="div" disablePadding>
                        {resources
                          .filter(x => x.options.menu == menu.name)
                          .map((resource, i) => (
                            <MenuItemLink
                              key={"m" + i}
                              to={`/${resource.name}`}
                              primaryText={resource.options.label || resource.name}
                              leftIcon={
                                resource.icon
                                  ? createElement(resource.icon)
                                  : undefined
                              }
                              onClick={onMenuClick}
                              className={this.props.classes.nested}
                            />
                          ))}
                      </List>
                    </Collapse>
                  </div>
                );
              })}
            </List>
          </div>
        );
      }
    }
    
    var MenuWithStyles = withStyles(menuStyles)(Menu);
    
    const MyMenu = withRouter(
      connect(state => ({
        resources: getResources(state)
      }))(MenuWithStyles)
    );
    
    const MyLayout = props => <Layout {...props} menu={MyMenu} />;
    
    const App = () => (
        <Admin      
          ...
          appLayout={MyLayout}
        >
          <Resource 
            ...
            options={{ label: 'Page 1' menu: "A" }}
          />
          <Resource 
            ...
            options={{ label: 'Page 2' menu: "A" }}
          />
          <Resource 
            ...
            options={{ label: 'Page 3' menu: "B" }}
          />
        </Admin>
      );
    
    0 讨论(0)
  • 2021-01-05 09:11

    The react-admin demo now shows a way to do so in examples/demo/src/layout/Menu.js:

    import React, { Component } from 'react';
    import PropTypes from 'prop-types';
    import { connect } from 'react-redux';
    import compose from 'recompose/compose';
    import SettingsIcon from '@material-ui/icons/Settings';
    import LabelIcon from '@material-ui/icons/Label';
    import { withRouter } from 'react-router-dom';
    import {
        translate,
        DashboardMenuItem,
        MenuItemLink,
        Responsive,
    } from 'react-admin';
    
    import visitors from '../visitors';
    import orders from '../orders';
    import invoices from '../invoices';
    import products from '../products';
    import categories from '../categories';
    import reviews from '../reviews';
    import SubMenu from './SubMenu';
    
    class Menu extends Component {
        state = {
            menuCatalog: false,
            menuSales: false,
            menuCustomers: false,
        };
    
        static propTypes = {
            onMenuClick: PropTypes.func,
            logout: PropTypes.object,
        };
    
        handleToggle = menu => {
            this.setState(state => ({ [menu]: !state[menu] }));
        };
    
        render() {
            const { onMenuClick, open, logout, translate } = this.props;
            return (
                <div>
                    {' '}
                    <DashboardMenuItem onClick={onMenuClick} />
                    <SubMenu
                        handleToggle={() => this.handleToggle('menuSales')}
                        isOpen={this.state.menuSales}
                        sidebarIsOpen={open}
                        name="pos.menu.sales"
                        icon={<orders.icon />}
                    >
                        <MenuItemLink
                            to={`/commands`}
                            primaryText={translate(`resources.commands.name`, {
                                smart_count: 2,
                            })}
                            leftIcon={<orders.icon />}
                            onClick={onMenuClick}
                        />
                        <MenuItemLink
                            to={`/invoices`}
                            primaryText={translate(`resources.invoices.name`, {
                                smart_count: 2,
                            })}
                            leftIcon={<invoices.icon />}
                            onClick={onMenuClick}
                        />
                    </SubMenu>
                    <SubMenu
                        handleToggle={() => this.handleToggle('menuCatalog')}
                        isOpen={this.state.menuCatalog}
                        sidebarIsOpen={open}
                        name="pos.menu.catalog"
                        icon={<products.icon />}
                    >
                        <MenuItemLink
                            to={`/products`}
                            primaryText={translate(`resources.products.name`, {
                                smart_count: 2,
                            })}
                            leftIcon={<products.icon />}
                            onClick={onMenuClick}
                        />
                        <MenuItemLink
                            to={`/categories`}
                            primaryText={translate(`resources.categories.name`, {
                                smart_count: 2,
                            })}
                            leftIcon={<categories.icon />}
                            onClick={onMenuClick}
                        />
                    </SubMenu>
                    <SubMenu
                        handleToggle={() => this.handleToggle('menuCustomer')}
                        isOpen={this.state.menuCustomer}
                        sidebarIsOpen={open}
                        name="pos.menu.customers"
                        icon={<visitors.icon />}
                    >
                        <MenuItemLink
                            to={`/customers`}
                            primaryText={translate(`resources.customers.name`, {
                                smart_count: 2,
                            })}
                            leftIcon={<visitors.icon />}
                            onClick={onMenuClick}
                        />
                        <MenuItemLink
                            to={`/segments`}
                            primaryText={translate(`resources.segments.name`, {
                                smart_count: 2,
                            })}
                            leftIcon={<LabelIcon />}
                            onClick={onMenuClick}
                        />
                    </SubMenu>
                    <MenuItemLink
                        to={`/reviews`}
                        primaryText={translate(`resources.reviews.name`, {
                            smart_count: 2,
                        })}
                        leftIcon={<reviews.icon />}
                        onClick={onMenuClick}
                    />
                    <Responsive
                        xsmall={
                            <MenuItemLink
                                to="/configuration"
                                primaryText={translate('pos.configuration')}
                                leftIcon={<SettingsIcon />}
                                onClick={onMenuClick}
                            />
                        }
                        medium={null}
                    />
                    <Responsive
                        small={logout}
                        medium={null} // Pass null to render nothing on larger devices
                    />
                </div>
            );
        }
    }
    
    const mapStateToProps = state => ({
        open: state.admin.ui.sidebarOpen,
        theme: state.theme,
        locale: state.i18n.locale,
    });
    
    const enhance = compose(
        withRouter,
        connect(
            mapStateToProps,
            {}
        ),
        translate
    );
    
    export default enhance(Menu);
    
    0 讨论(0)
提交回复
热议问题