Wrapping SideNavCat


Topic: Wrapping SideNavCat

lpokoradi pro premium priority asked 5 years ago

Hi,

I would like to create a component to group together SideNav categories, so I could render them with one condition.

<MDBSideNavNav>
    { this.state.user.roles.includes('ROLE_ADMINISTRATOR') ? <AdministratorSideNav /> : null }
...
</MDBSideNavNav>

The AdministratorSideNav component looks like:

class AdministratorSideNav extends Component {
render() {
    return [
        <MDBSideNavCat
            key='company-admin-cat'
            name="Company Administration "
            id="company-admin-cat"
            icon="chevron-right">
            <MDBSideNavItem href='/admin/location'>Locations</MDBSideNavItem>
            <MDBSideNavItem href='/admin/user'>Users</MDBSideNavItem>
            <MDBSideNavItem href='/admin/team'>Teams</MDBSideNavItem>
        </MDBSideNavCat>,
        ... more MDBSideNavCat
    ];
}};

The rendering looks okay. The only problem is that clicking is not working. Clicking on the MDBSideNavCat (Company Administration in my example) only results in the ripple effect, but the category is not opening.

Is there any trick I am missing?

Regards, Laszlo


Piotr Glejzer staff commented 5 years ago

Did you try to put all URL address into href?


lpokoradi pro premium priority commented 5 years ago

Sorry, but I don't get it. What do you mean "put all URL address into href"?


Piotr Glejzer staff commented 5 years ago

Oh sorry, I thought about a different problem.

So, did you try to use props isOpen?


lpokoradi pro premium priority commented 5 years ago

If I change the value of isOpen from false to true, in the React DevTools, yes the category opens as it should. But the question why it is not working.


lpokoradi pro premium priority commented 5 years ago

I would create a snippet for you, but "Something bad happened during initialization ;("


Piotr Glejzer staff commented 5 years ago

You can copy and paste all code here, I will check


lpokoradi pro premium priority answered 5 years ago

App.jsx:

import React, {Component} from 'react';

import '@fortawesome/fontawesome-free/css/all.min.css';
import "bootstrap-css-only/css/bootstrap.min.css";
import "mdbreact/dist/css/mdb.css";
import NavigationPage from "./Navigation/NavigationPage";
import {BrowserRouter} from "react-router-dom";

class App extends Component {
    constructor() {
        super();

        this.state = {
            locations: null
        };
    }

    componentDidMount() {
    }

    render() {
        return (
            <BrowserRouter>
                <NavigationPage />
            </BrowserRouter>

        );
    }
}

App.propTypes = {};

export default App;

lpokoradi pro premium priority answered 5 years ago

NavigationPage.jsx:

import React from "react";
import {
    MDBInput,
    MDBNavbar,
    MDBNavbarNav,
    MDBNavItem,
    MDBNavLink,
    MDBDropdown,
    MDBDropdownToggle,
    MDBDropdownMenu,
    MDBDropdownItem,
    MDBIcon,
    MDBSideNavItem,
    MDBSideNavCat,
    MDBSideNavNav,
    MDBSideNav,
    MDBContainer
} from "mdbreact";
import {Link, Route, Switch} from "react-router-dom";
import AdministratorSideNav from "./SideNav/AdministratorSideNav";

class NavigationPage extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            isSideBarShown: false,
            user: {
                roles: ['ROLE_USER', 'ROLE_ADMINISTRATOR', 'ROLE_DELIVERY']
            }
        };
    }

    handleToggleClickA = () => {
        this.setState({
            isSideBarShown: !this.state.isSideBarShown
        });
    };

    render() {
        const mainStyle = {
            paddingTop: "5rem"
        };

        const specialCaseNavbarStyles = {
            WebkitBoxOrient: "horizontal",
            flexDirection: "row"
        };

        return (
            <div className="navy-blue-skin">
                <MDBSideNav
                    logo="https://mdbootstrap.com/img/logo/mdb-transparent.png"
                    triggerOpening={this.state.isSideBarShown}
                    bg="https://mdbootstrap.com/img/Photos/Others/sidenav4.jpg"
                    mask="strong"
                    hidden>
                    <li>
                        <ul className="social">
                            <li>
                                <a href="#!">
                                    <MDBIcon fab icon="facebook-f"/>
                                </a>
                            </li>
                            <li>
                                <a href="#!">
                                    <MDBIcon fab icon="pinterest"/>
                                </a>
                            </li>
                            <li>
                                <a href="#!">
                                    <MDBIcon fab icon="google-plus-g"/>
                                </a>
                            </li>
                            <li>
                                <a href="#!">
                                    <MDBIcon fab icon="twitter"/>
                                </a>
                            </li>
                        </ul>
                    </li>
                    <MDBInput
                        type="text"
                        hint="Search"
                        style={{
                            color: "#fff",
                            padding: "0 10px 8px 30px",
                            boxSizing: "border-box"
                        }}
                    />
                    <MDBSideNavNav>
                        { this.state.user.roles.includes('ROLE_ADMINISTRATOR') ? <AdministratorSideNav /> : null }
                        <MDBSideNavCat
                            name="Submit blog"
                            id="submit-blog-cat"
                            icon="chevron-right">
                            <Link to="submit">Submit Listing</Link>
                            <MDBSideNavItem href="/test">Submit listing</MDBSideNavItem>
                            <MDBSideNavItem>Registration form</MDBSideNavItem>
                        </MDBSideNavCat>
                    </MDBSideNavNav>
                </MDBSideNav>
                <MDBNavbar double expand="md" fixed="top" scrolling>
                    <MDBNavbarNav left>
                        <MDBNavItem>
                            <div
                                onClick={this.handleToggleClickA}
                                key="sideNavToggleA"
                                style={{
                                    lineHeight: "32px",
                                    marginRight: "1em",
                                    verticalAlign: "middle"
                                }}
                            >
                                <MDBIcon icon="bars" color="white" size="2x"/>
                            </div>
                        </MDBNavItem>
                        <MDBNavItem className="d-none d-md-inline" style={{paddingTop: 5}}>
                            Material Design for Bootstrap
                        </MDBNavItem>
                    </MDBNavbarNav>
                    <MDBNavbarNav right style={specialCaseNavbarStyles}>
                        <MDBNavItem active>
                            <MDBNavLink to="#!">
                                <MDBIcon icon="envelope" className="d-inline-inline"/>{" "}
                                <div className="d-none d-md-inline">Contact</div>
                            </MDBNavLink>
                        </MDBNavItem>
                        <MDBNavItem>
                            <MDBNavLink to="#!">
                                <MDBIcon far icon="comments" className="d-inline-inline"/>{" "}
                                <div className="d-none d-md-inline">Support</div>
                            </MDBNavLink>
                        </MDBNavItem>
                        <MDBNavItem>
                            <MDBNavLink to="#!">
                                <MDBIcon icon="user" className="d-inline-inline"/>{" "}
                                <div className="d-none d-md-inline">Account</div>
                            </MDBNavLink>
                        </MDBNavItem>
                        <MDBNavItem>
                            <MDBDropdown>
                                <MDBDropdownToggle nav caret>
                                    <div className="d-none d-md-inline">Dropdown</div>
                                </MDBDropdownToggle>
                                <MDBDropdownMenu right>
                                    <MDBDropdownItem href="#!">Action</MDBDropdownItem>
                                    <MDBDropdownItem href="#!">Another Action</MDBDropdownItem>
                                    <MDBDropdownItem href="#!">Something else here</MDBDropdownItem>
                                    <MDBDropdownItem href="#!">Something else here</MDBDropdownItem>
                                </MDBDropdownMenu>
                            </MDBDropdown>
                        </MDBNavItem>
                    </MDBNavbarNav>
                </MDBNavbar>
                <main style={mainStyle}>
                    <MDBContainer fluid style={{height: 2000}} className="mt-5">
                        <Switch>
                            <Route path='/' exact render={()=><h1>Test</h1>}></Route>
                            <Route path='/admin/location' render={()=><h1>Location administration</h1>}></Route>
                            <Route path='/admin/user' render={()=><h1>User administration</h1>}></Route>
                            <Route path='/admin/team' render={()=><h1>Team administration</h1>}></Route>
                        </Switch>
                    </MDBContainer>
                </main>
            </div>
        );
    }
}

export default NavigationPage;

lpokoradi pro premium priority answered 5 years ago

AdministratorSideNav.jsx:

import React, {Component} from 'react';
import {MDBSideNavCat, MDBSideNavItem} from "mdbreact";
import {withRouter} from "react-router-dom";

class AdministratorSideNav extends Component {
    render() {
        return (
            <React.Fragment>
                <MDBSideNavCat
                    key="company-admin-cat"
                    name="Company Administration "
                    id="company-admin-cat"
                    icon="chevron-right">
                    <MDBSideNavItem href="/admin/location">Locations</MDBSideNavItem>
                    <MDBSideNavItem href="/admin/user">Users</MDBSideNavItem>
                    <MDBSideNavItem href="/admin/team">Teams</MDBSideNavItem>
                </MDBSideNavCat>
                <MDBSideNavCat
                    key='assessment-admin-cat'
                    name="Assessment Administration "
                    id="assessment-admin-cat"
                    icon="chevron-right">
                    <MDBSideNavItem href='test'>Submit listing</MDBSideNavItem>
                    <MDBSideNavItem>Registration form</MDBSideNavItem>
                </MDBSideNavCat>
            </React.Fragment>
        );
    }
};

export default withRouter(AdministratorSideNav);

lpokoradi pro premium priority answered 5 years ago

The "Submit blog" SideNavCat is working perfectly, but my AdministratorSideNav component is just rendered correctly, but the click event is not opening the category.


Piotr Glejzer staff answered 5 years ago

Ok, I figured it out.

So the main problem is that our component SideNavNav has a React.Children method on what type of component name is returning and it if is a SideNavCat return a React.cloneElement with prop onClick and isOpen what number is clicked and what component is open at the moment.

If you are returning elements like that:

    {this.state.user.roles.includes('ROLE_ADMINISTRATOR') ? (
      <>
        <MDBSideNavCat
          key='company-admin-cat'
          name='Company Administration '
          id='company-admin-cat'
          icon='chevron-right'
        >
          <MDBSideNavItem href='/admin/location'>Locations</MDBSideNavItem>
          <MDBSideNavItem href='/admin/user'>Users</MDBSideNavItem>
          <MDBSideNavItem href='/admin/team'>Teams</MDBSideNavItem>
        </MDBSideNavCat>
        <MDBSideNavCat
          key='assessment-admin-cat'
          name='Assessment Administration '
          id='assessment-admin-cat'
          icon='chevron-right'
          isOpenID='3'
        >
          <MDBSideNavItem href='test'>Submit listing</MDBSideNavItem>
          <MDBSideNavItem>Registration form</MDBSideNavItem>
        </MDBSideNavCat>{' '}
      </>
    ) : null}

It is not working as I said because the first displayName is a react.fragment instead SideNavCat.

The solution for that is to split the above condition to separate objects. Like this:

   {this.state.user.roles.includes('ROLE_ADMINISTRATOR') ? (
      <MDBSideNavCat
        key='assessment-admin-cat'
        name='Assessment Administration '
        id='assessment-admin-cat'
        icon='chevron-right'
        isOpenID='3'
      >
        <MDBSideNavItem href='test'>Submit listing</MDBSideNavItem>
        <MDBSideNavItem>Registration form</MDBSideNavItem>
      </MDBSideNavCat>
    ) : null}

    {this.state.user.roles.includes('ROLE_ADMINISTRATOR') ? (
      <MDBSideNavCat
        key='company-admin-cat'
        name='Company Administration '
        id='company-admin-cat'
        icon='chevron-right'
      >
        <MDBSideNavItem href='/admin/location'>Locations</MDBSideNavItem>
        <MDBSideNavItem href='/admin/user'>Users</MDBSideNavItem>
        <MDBSideNavItem href='/admin/team'>Teams</MDBSideNavItem>
      </MDBSideNavCat>
    ) : null}

Here is a fully working NavigationPage

import React from "react";
import {
  MDBInput,
  MDBNavbar,
  MDBNavbarNav,
  MDBNavItem,
  MDBNavLink,
  MDBDropdown,
  MDBDropdownToggle,
  MDBDropdownMenu,
  MDBDropdownItem,
  MDBIcon,
  MDBSideNavItem,
  MDBSideNavCat,
  MDBSideNavNav,
  MDBSideNav,
  MDBContainer
} from "mdbreact";
import { Link, Route, Switch } from "react-router-dom";

class NavigationPage extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isSideBarShown: false,
      user: {
        roles: ["ROLE_USER", "ROLE_ADMINISTRATOR", "ROLE_DELIVERY"]
      }
    };
  }

  handleToggleClickA = () => {
    this.setState({
      isSideBarShown: !this.state.isSideBarShown
    });
  };

  render() {
    const mainStyle = {
      paddingTop: "5rem"
    };

    const specialCaseNavbarStyles = {
      WebkitBoxOrient: "horizontal",
      flexDirection: "row"
    };

    return (
      <div className="navy-blue-skin">
        <MDBSideNav
          logo="https://mdbootstrap.com/img/logo/mdb-transparent.png"
          triggerOpening={this.state.isSideBarShown}
          bg="https://mdbootstrap.com/img/Photos/Others/sidenav4.jpg"
          mask="strong"
          hidden
        >
          <li>
            <ul className="social">
              <li>
                <a href="#!">
                  <MDBIcon fab icon="facebook-f" />
                </a>
              </li>
              <li>
                <a href="#!">
                  <MDBIcon fab icon="pinterest" />
                </a>
              </li>
              <li>
                <a href="#!">
                  <MDBIcon fab icon="google-plus-g" />
                </a>
              </li>
              <li>
                <a href="#!">
                  <MDBIcon fab icon="twitter" />
                </a>
              </li>
            </ul>
          </li>
          <MDBInput
            type="text"
            hint="Search"
            style={{
              color: "#fff",
              padding: "0 10px 8px 30px",
              boxSizing: "border-box"
            }}
          />
          <MDBSideNavNav>
            {this.state.user.roles.includes("ROLE_ADMINISTRATOR") ? (
              <MDBSideNavCat
                key="company-admin-cat"
                name="Company Administration "
                id="company-admin-cat"
                icon="chevron-right"
              >
                <MDBSideNavItem href="/admin/location">
                  Locations
                </MDBSideNavItem>
                <MDBSideNavItem href="/admin/user">Users</MDBSideNavItem>
                <MDBSideNavItem href="/admin/team">Teams</MDBSideNavItem>
              </MDBSideNavCat>
            ) : null}
            {this.state.user.roles.includes("ROLE_ADMINISTRATOR") ? (
              <MDBSideNavCat
                key="assessment-admin-cat"
                name="Assessment Administration "
                id="assessment-admin-cat"
                icon="chevron-right"
                isOpenID="3"
              >
                <MDBSideNavItem href="test">Submit listing</MDBSideNavItem>
                <MDBSideNavItem>Registration form</MDBSideNavItem>
              </MDBSideNavCat>
            ) : null}
            <MDBSideNavCat
              name="Submit blog"
              id="submit-blog-cat"
              icon="chevron-right"
            >
              <Link to="submit">Submit Listing</Link>
              <MDBSideNavItem href="/test">Submit listing</MDBSideNavItem>
              <MDBSideNavItem>Registration form</MDBSideNavItem>
            </MDBSideNavCat>
            <MDBSideNavCat
              name="Submit blog1"
              id="submit-blog-cat1"
              icon="chevron-right1"
            >
              <Link to="submit">Submit Listing</Link>
              <MDBSideNavItem href="/test">Submit listing</MDBSideNavItem>
              <MDBSideNavItem>Registration form</MDBSideNavItem>
            </MDBSideNavCat>
          </MDBSideNavNav>
        </MDBSideNav>
        <MDBNavbar double expand="md" fixed="top" scrolling>
          <MDBNavbarNav left>
            <MDBNavItem>
              <div
                onClick={this.handleToggleClickA}
                key="sideNavToggleA"
                style={{
                  lineHeight: "32px",
                  marginRight: "1em",
                  verticalAlign: "middle"
                }}
              >
                <MDBIcon icon="bars" color="white" size="2x" />
              </div>
            </MDBNavItem>
            <MDBNavItem
              className="d-none d-md-inline"
              style={{ paddingTop: 5 }}
            >
              Material Design for Bootstrap
            </MDBNavItem>
          </MDBNavbarNav>
          <MDBNavbarNav right style={specialCaseNavbarStyles}>
            <MDBNavItem active>
              <MDBNavLink to="#!">
                <MDBIcon icon="envelope" className="d-inline-inline" />{" "}
                <div className="d-none d-md-inline">Contact</div>
              </MDBNavLink>
            </MDBNavItem>
            <MDBNavItem>
              <MDBNavLink to="#!">
                <MDBIcon far icon="comments" className="d-inline-inline" />{" "}
                <div className="d-none d-md-inline">Support</div>
              </MDBNavLink>
            </MDBNavItem>
            <MDBNavItem>
              <MDBNavLink to="#!">
                <MDBIcon icon="user" className="d-inline-inline" />{" "}
                <div className="d-none d-md-inline">Account</div>
              </MDBNavLink>
            </MDBNavItem>
            <MDBNavItem>
              <MDBDropdown>
                <MDBDropdownToggle nav caret>
                  <div className="d-none d-md-inline">Dropdown</div>
                </MDBDropdownToggle>
                <MDBDropdownMenu right>
                  <MDBDropdownItem href="#!">Action</MDBDropdownItem>
                  <MDBDropdownItem href="#!">Another Action</MDBDropdownItem>
                  <MDBDropdownItem href="#!">
                    Something else here
                  </MDBDropdownItem>
                  <MDBDropdownItem href="#!">
                    Something else here
                  </MDBDropdownItem>
                </MDBDropdownMenu>
              </MDBDropdown>
            </MDBNavItem>
          </MDBNavbarNav>
        </MDBNavbar>
        <main style={mainStyle}>
          <MDBContainer fluid style={{ height: 2000 }} className="mt-5">
            <Switch>
              <Route path="/" exact render={() => <h1>Test</h1>}></Route>
              <Route
                path="/admin/location"
                render={() => <h1>Location administration</h1>}
              ></Route>
              <Route
                path="/admin/user"
                render={() => <h1>User administration</h1>}
              ></Route>
              <Route
                path="/admin/team"
                render={() => <h1>Team administration</h1>}
              ></Route>
            </Switch>
          </MDBContainer>
        </main>
      </div>
    );
  }
}

export default NavigationPage;

lpokoradi pro premium priority answered 5 years ago

Hi Piotr,

Thanks for the reply, I already knew that workaround is working, but it doesn't help me to have clean code.

So will it be possible decoupling like I would like to?


Piotr Glejzer staff commented 5 years ago

Is not possible to do it without duplicated a code. I added task to fix this. Sorry about that.


Please insert min. 20 characters.

FREE CONSULTATION

Hire our experts to build a dedicated project. We'll analyze your business requirements, for free.

Status

Answered

Specification of the issue
  • User: Pro
  • Premium support: Yes
  • Technology: MDB React
  • MDB Version: 4.25.2
  • Device: PC
  • Browser: Chrome
  • OS: Windows 10
  • Provided sample code: No
  • Provided link: No
Tags