Open nested menu in main menu - material-ui (react) - reactjs

(I don't have enough reputation to post more than 2 links, therefore I am writitng out the URLS)
In material-ui (w*w.material-ui.com) I can program nested menus and dropdown menus. But I haven`t found an example to open the nested menus in the main menu.
With nested menus and dropdown menus the nested menus open every time as a new window beside or above the main menu. Like this example: Menu with nested menu opened to the right
But I would like to have the nested menus opened in the main menu. Like this example:
Nested menus open in main menu
Can someone please show me an example how to achieve this.
Thanks

You're using the wrong component. Use a List with ListItems that have NestedItems
<List>
<Subheader>Nested List Items</Subheader>
<ListItem primaryText="Sent mail" leftIcon={<ContentSend />} />
<ListItem primaryText="Drafts" leftIcon={<ContentDrafts />} />
<ListItem
primaryText="Inbox"
leftIcon={<ContentInbox />}
initiallyOpen={true}
primaryTogglesNestedList={true}
nestedItems={[
<ListItem
key={1}
primaryText="Starred"
leftIcon={<ActionGrade />}
/>,
<ListItem
key={2}
primaryText="Sent Mail"
leftIcon={<ContentSend />}
disabled={true}
nestedItems={[
<ListItem key={1} primaryText="Drafts" leftIcon={<ContentDrafts />} />,
]}
/>,
<ListItem
key={3}
primaryText="Inbox"
leftIcon={<ContentInbox />}
open={this.state.open}
onNestedListToggle={this.handleNestedListToggle}
nestedItems={[
<ListItem key={1} primaryText="Drafts" leftIcon={<ContentDrafts />} />,
]}
/>,
]}
/>
</List>

Related

Child component updates parent state unexpectedly in react

I'm using react with MUI. I'm using the MUI List component which each list may have a nested list in it. the problem is when I open a nested list, the parent component gets closed. I don't know what I am doing wrong. You could use this CodeSandbox.
Here is an image of my app: Gif
Your problem is you add onClick on ListItem which contains all other sub-items, so that means whenever you trigger click on any sub-item, you accidentally trigger the main ListItem too. That's why you've seen the main menu item gets collapsed when you click on any sub-item. You can read more about event propagation.
The easiest fix is you should move onClick={handleToggleCollapse} from ListItem to ListItemButton
<ListItem {...listItemProps} sx={{ display: "block" }}>
<ListItemButton onClick={handleToggleCollapse}>
{icon && <ListItemIcon>{icon}</ListItemIcon>}
<ListItemText primary={text} />
{open ? (
<IoIosArrowUp className="text-lg" />
) : (
<IoIosArrowDown className="text-lg" />
)}
</ListItemButton>
<Collapse in={open} timeout={300}>
<List disablePadding>
<ListItems listItems={nestedItems} />
</List>
</Collapse>
</ListItem>
For event propagation prevention, you should modify handleToggleCollapse like below
function handleToggleCollapse(e: SyntheticEvent) {
e.stopPropagation();
setOpen((prev) => !prev);
}
Sandbox

Unable to solve the Menu bar issue using reactjs?

I'm new to Framework and i have an issue with me sidebar which is showing Table tab as default but it should not show any tab's page as clicked. By default it should show nothing. When we click on a particular tab then it should show color on the tab of the sidebar. If i give -1 then the color is getting disappeared on the menu tab but the Tab's page remain as it is. Is it possible to give pathname. how to fix by giving id ? . If Yes Can anyone help me in fixing this issue?
Here is the code:
<Drawer
className={classes.drawer}
variant="permanent"
classes={{
paper: classes.drawerPaper
}}
>
<div className={classes.toolbar} />
<List>
{["table", "home"].map((item, index) => {
const Icon = itemsConfig[item].icon;
return (
<ListItem
component={Link}
to={itemsConfig[item].link}
selected={selectedIndex === index}
onClick={event => handleListItemClick(event, index)}
button
key={item}
>
<ListItemIcon>
<Icon />
</ListItemIcon>
<ListItemText primary={itemsConfig[item].text} />
</ListItem>
);
})}
</List>
</Drawer>
Here is whole code: "https://codesandbox.io/s/fervent-browser-ecz7z"
Can anyone help me in this ?
Define your state, that holds the selected index in your <Layout /> component. Define function that manipulate that state and pass it to , <Home /> andcomponents along with the newly defined state. Finally call the function after the initial rendering of the component. For the (class component) use:
componentDidMount() {
this.props.setTabIndex(this.props.index);
}
For the <Table /> use:
useEffect(() => {
props.setTabIndex(props.index);
}, []);
The full result is posted here: https://codesandbox.io/s/cold-mountain-hlhk8?

how to make list navigation in material ui react

I want navigation like https://material-ui.com/getting-started/installation/ and same ul > li > a> sapn structure like material ui website made in his side navigation. and I want the same effect also.
I used a lot of tricks but it restults fail. Please help
here is my code
<Router>
<div>
<List>
{[0, 1, 2, 3].map(value => (
<ListItem key={value} className={classes.listItem}>
<Link button to="/about">
<ListItemText primary={`Line item ${value + 1}`} />
</Link>
</ListItem>
))}
</List>
</div>
</Router>

How will prevent triggering navLink/link in react router when click right icon button with nested list item? Material UI

I have a sample code here: ListItem with nested list I want to prevent the link and trigger the nested list. Or I want when I click the rightIconButton only triggers the nested list not the link.
<ListItem
value={3}
primaryText="My Collection"
leftIcon={<Avatar src="http://i.imgur.com/fmvLZGS.png" />}
initiallyOpen={false}
containerElement={<NavLink to="/CollectionPage" />}
nestedItems={[
<ListItem
value={4}
key={1}
primaryText="Wines"/>,
<ListItem
value={5}
key={2}
primaryText="Arts"/>,
<ListItem
value={6}
key={3}
primaryText="Vehicles"/>
]} />
Thank you!

React / Material-UI detect last ListItem in List

I am using material-ui with React. I have a listview that looks like this:
<List>
<Subheader>List Title</Subheader>
<ListItem primaryText="Option One" />
<Divider />
<ListItem primaryText="Option Two" />
<Divider />
<ListItem primaryText="Option Three" />
</List>
There is a divider between each item but none before the first item or after the last. So far so good.
I have just implemented a simple wrapper that renders or does not render a list item based on a user permission. So it looks like this:
<List>
<Subheader>List Title</Subheader>
<Restricted permission={1}>
<ListItem primaryText="Option One" />
</Restricted>
<Divider />
<Restricted permission={2}>
<ListItem primaryText="Option Two" />
</Restricted>
<Divider />
<Restricted permission={4}>
<ListItem primaryText="Option Three" />
</Restricted>
</List>
The Restricted component compares the users permission with the specified one and returns either the child component or null. This all works but obviously retains the dividers if the option is not rendered.
I could wrap the divider within the Restricted component along with the ListItem which in most cases renders what I want but it leaves a divider at the bottom if the last item is not rendered. What I need is a way of saying don't render the divider if this is the last item in the list.
At the moment my plan is to programmatically generate an array of displayable list items and then render this in a loop with the appropriate dividers. But this will mean that I will have to the the decision logic in each component that uses it instead of a single wrapper. That feels wrong.
Is there some aspect of React/material-ui that I have missed that will enable me the achieve what I want in a more elegant way?
I propose the following solution. First move your representation of list to variable
const allOptions = [
{ text: "Option 1", permission: 1 },
{ text: "Option 2", permission: 2 },
{ text: "Option 3", permission: 4 }
]
then use filter to get only permitted options
const permittedOptions = listItems.filter(checkPermission)
use map to create list items
const listItems = permittedOptions.map(option => <ListeItem text={option.text} />)
now put dividers only if there is a next and prev list item
const listItemsWithDividers = [];
listItems.forEach((item, index) => {
listItemsWithDividers.push(item)
if (listItems[index + 1] !== undefined) {
listItemsWithDividers.push(<Divider />)
}
})
and finally render it
<List>
<Subheader>List Title</Subheader>
{listItemsWithDividers}
</List>
A more cost effective approach would look something like this
<div>
<List>
{items.map((item) => (
<div key={item.id}>
<ListItem>
<ListItemText primary={item.name} />
</ListItem>
{item.id !== items.length ? <Divider /> : null}
</div>
))}
</List>
</div>
{items.data.map((item, index) => (
<ListItem button key={index} divider={index < items.length - 1}>
...
</ListItem>
)})

Resources