How can i create a multiple nested list - javascript

so i am trying to create a list, whereby a list is displaying many items, and two of the items are expandable, and expanding them shows more items(subitems). I have managed to display the list, and the sub-lists, however, clicking either one of the expandable items, expands both items and not just the single one i clicked.
So firstly, i have seperated the listItems as a data structure where i can retrieve them. This is the list Items:
// Skills list in the About Page
export const listItems = [
{
listText: 'Html',
listIcon: <SendIcon/>
},
{
listText: 'CSS',
listIcon: <DraftsIcon />
},
{
listText: 'JavaScript',
listIcon: <InboxIcon />
},
{
listText: 'React',
listIcon: <SendIcon/>,
expan: true,
// SubItems
firstText:'React-Router',
secondText:'React-Navigation',
thirdText:'React-Native',
},
{
listText: 'Database',
listIcon: <DraftsIcon />,
expan: true,
// SubItems
firstText:'FireBase',
secondText:'SQL',
},
{
listText: 'ReactJs',
listIcon: <DraftsIcon />
},
{
listText: 'ReactJs',
listIcon: <DraftsIcon />
}]
This is the code where i am trying to implement the list:
import React, { Fragment } from 'react'
import Styles from './Styles'
// ListItems
import List from '#material-ui/core/List';
import ListItem from '#material-ui/core/ListItem';
import ListItemIcon from '#material-ui/core/ListItemIcon';
import ListItemText from '#material-ui/core/ListItemText';
import ExpandLess from '#material-ui/icons/ExpandLess';
import ExpandMore from '#material-ui/icons/ExpandMore';
import StarBorder from '#material-ui/icons/StarBorder';
import Collapse from '#material-ui/core/Collapse';
import {listItems} from './ListItems'
const AboutSkills = () => {
const classes = Styles()
const [open, setOpen] = React.useState(false);
const handleClick = () => {
setOpen(!open);
};
const outputList = () => (
<>
<List
style={{color:'white'}}
component="nav"
className={classes.root}
>
{ //Map through the ListItems and...
listItems.map((item, index) => {
// if expandable items exist, expand them
if(item.expan)
{
{/* Use fragment instad of <></> because key attribute is required */}
return <Fragment key={index}>
<ListItem button onClick={handleClick} className={classes.aboutList}>
<ListItemIcon className={classes.aboutIcon}>
{item.listIcon}
</ListItemIcon>
<ListItemText primary={item.listText} />
{open ? <ExpandLess /> : <ExpandMore />}
</ListItem>
<Collapse in={open} timeout="auto" unmountOnExit>
<List component="div" disablePadding>
<ListItem button className={classes.nested}>
<ListItemIcon>
<StarBorder />
</ListItemIcon>
<ListItemText classes={{primary:classes.expanText}}
primary={item.firstText} />
</ListItem>
{/* {console.log(item.secondText)} */}
{ item.secondText //if seconditem exists...
? <ListItem button className={classes.nested}>
<ListItemIcon>
<StarBorder />
</ListItemIcon>
<ListItemText classes=
{{primary:classes.expanText}} primary={item.secondText} />
</ListItem>
: console.log('No Third Item')}
{ item.thirdText //if seconditem exists...
? <ListItem button className={classes.nested}>
<ListItemIcon>
<StarBorder />
</ListItemIcon>
<ListItemText classes=
{{primary:classes.expanText}} primary={item.thirdText} />
</ListItem>
: console.log('No Third Item')}
</List>
</Collapse>
</Fragment>
} else {
return <ListItem button className={classes.aboutList} key={index}>
<ListItemIcon className={classes.aboutIcon}>
{item.listIcon}
</ListItemIcon>
<ListItemText classes={{primary:classes.unExpanText}} primary=
{item.listText} />
</ListItem>
}
})}
</List>
</>
)
return (
outputList()
)
}
export default AboutSkills

My answer in this thread is pretty much what you are searching for.
Just adapt the code according to your situation.

Related

Getting Error an error message for Collapse component on Material UI

I am trying to build a hamburger menu using Material UI List on Next.js similar to Nested List example on Material UI docs. However, I am keep getting error if I use "collapse" on my code. If I remove collapse then the other parts of the code works fine.
Can anyone tell me what am I doing wrong?
screenshot of an error message
I am trying to build similar to this
import * as React from "react";
import { useState } from "react";
import IconButton from "#mui/material/IconButton";
import ListSubheader from "#mui/material/ListSubheader";
import { Drawer } from "#mui/material";
import List from "#mui/material/List";
import ListItem from "#mui/material/ListItem";
import ListItemButton from "#mui/material/ListItemButton";
import ListItemIcon from "#mui/material/ListItemIcon";
import ListItemText from "#mui/material/ListItemText";
import MenuIcon from "#mui/icons-material/Menu";
import { ExpandLess, ExpandMore } from "#mui/icons-material";
import Collapse from "#mui/material";
const myMenu = [
{
title: "about",
},
{
title: "services",
submenu: [{ title: "Digital Marketing" }, { title: "Promotion" }],
},
{
title: "blog",
},
{
title: "contact",
},
];
const ResponsiveAppBar = () => {
const [openDrawer, setOpenDrawer] = useState(false);
const [open, setOpen] = React.useState(false);
const handleClick = () => {
setOpen(!open);
};
return (
<React.Fragment>
<Drawer
anchor="right"
open={openDrawer}
onClose={() => setOpenDrawer(false)}
>
<List
sx={{ width: "100%", maxWidth: 360, bgcolor: "background.paper" }}
component="nav"
aria-labelledby="nested-list-subheader"
subheader={
<ListSubheader component="div" id="nested-list-subheader">
Navigation
</ListSubheader>
}
>
{myMenu.map((page, index) =>
page.submenu ? (
<div>
<ListItemButton key={index} onClick={handleClick}>
<ListItemText>{page.title}</ListItemText>
{open ? <ExpandLess /> : <ExpandMore />}
</ListItemButton>
<Collapse in={open} timeout="auto" unmountOnExit>
<List component="div" disablePadding>
{page.submenu.map((sub, index) => {
return (
<ListItemButton key={index}>
<ListItem key={index}>
<ListItemText>{sub.title}</ListItemText>
</ListItem>
</ListItemButton>
);
})}
</List>
</Collapse>
</div>
) : (
<ListItemButton key={index}>
<ListItemIcon>
<ListItemText>{page.title}</ListItemText>
</ListItemIcon>
</ListItemButton>
)
)}
</List>
</Drawer>
<IconButton
sx={{ color: "black", marginLeft: "auto" }}
onClick={() => setOpenDrawer(!openDrawer)}
>
<MenuIcon color="white" />
</IconButton>
</React.Fragment>
);
};
export default ResponsiveAppBar;
The culprit is an incorrect import of Collapse:
import Collapse from "#mui/material";
Since Collapse is a named import, you must import it in one of these two ways:
import { Collapse } from "#mui/material";
// Alternatively
import Collapse from "#mui/material/Collapse";

Have two secondary action elements in a list

I have created a list in react which has the following structure:
Avatar
Text
Edit icon
Delete icon
I have created the structure fine until the delete icon. How can I add this? Currently, it is overlapping the edit icon as both are ListItemSecondaryAction but I can't find on the documentation how to add an additional object and what it should be called? https://material-ui.com/components/lists/
Current implementation:
<List>
<ListItemAvatar>
<Avatar src="image" />
</ListItemAvatar>
<ListItemText primary="name" />
<ListItemSecondaryAction>
<IconButton>
<EditIcon />
</IconButton>
</ListItemSecondaryAction>
<ListItemSecondaryAction>
<IconButton>
<DeleteIcon />
</IconButton>
</ListItemSecondaryAction>
</List>
It is almost sufficient to just put both actions in one ListItemSecondaryAction (as indicated by comments and another answer). The only issue is that if you have long content it will overlap the first icon.
Here are the styles for the secondary action from ListItem:
/* Styles applied to the `component` element if `children` includes `ListItemSecondaryAction`. */
secondaryAction: {
// Add some space to avoid collision as `ListItemSecondaryAction`
// is absolutely positioned.
paddingRight: 48,
},
The paddingRight: 48 will not be sufficient for two icons. You can customize this as follows:
const ListItemWithWiderSecondaryAction = withStyles({
secondaryAction: {
paddingRight: 96
}
})(ListItem);
Here is a full working v4 example (v5 example further down) that shows the first two list items without this customization (so overlap occurs) and the second two with the fix:
import React from "react";
import { makeStyles, withStyles } from "#material-ui/core/styles";
import List from "#material-ui/core/List";
import ListItem from "#material-ui/core/ListItem";
import ListItemIcon from "#material-ui/core/ListItemIcon";
import ListItemSecondaryAction from "#material-ui/core/ListItemSecondaryAction";
import ListItemText from "#material-ui/core/ListItemText";
import Checkbox from "#material-ui/core/Checkbox";
import IconButton from "#material-ui/core/IconButton";
import CommentIcon from "#material-ui/icons/Comment";
import DeleteIcon from "#material-ui/icons/Delete";
const useStyles = makeStyles(theme => ({
root: {
width: "100%",
maxWidth: 360,
backgroundColor: theme.palette.background.paper
}
}));
const ListItemWithWiderSecondaryAction = withStyles({
secondaryAction: {
paddingRight: 96
}
})(ListItem);
export default function CheckboxList() {
const classes = useStyles();
const [checked, setChecked] = React.useState([0]);
const handleToggle = value => () => {
const currentIndex = checked.indexOf(value);
const newChecked = [...checked];
if (currentIndex === -1) {
newChecked.push(value);
} else {
newChecked.splice(currentIndex, 1);
}
setChecked(newChecked);
};
return (
<>
<List className={classes.root}>
{[0, 1].map(value => {
const labelId = `checkbox-list-label-${value}`;
return (
<ListItem
key={value}
role={undefined}
dense
button
onClick={handleToggle(value)}
>
<ListItemIcon>
<Checkbox
edge="start"
checked={checked.indexOf(value) !== -1}
tabIndex={-1}
disableRipple
inputProps={{ "aria-labelledby": labelId }}
/>
</ListItemIcon>
<ListItemText
id={labelId}
primary={`Line item ${value +
1} with some more text to make it longer`}
/>
<ListItemSecondaryAction>
<IconButton aria-label="comments">
<CommentIcon />
</IconButton>
<IconButton edge="end" aria-label="delete">
<DeleteIcon />
</IconButton>
</ListItemSecondaryAction>
</ListItem>
);
})}
</List>
<List className={classes.root}>
{[2, 3].map(value => {
const labelId = `checkbox-list-label-${value}`;
return (
<ListItemWithWiderSecondaryAction
key={value}
role={undefined}
dense
button
onClick={handleToggle(value)}
>
<ListItemIcon>
<Checkbox
edge="start"
checked={checked.indexOf(value) !== -1}
tabIndex={-1}
disableRipple
inputProps={{ "aria-labelledby": labelId }}
/>
</ListItemIcon>
<ListItemText
id={labelId}
primary={`Line item ${value +
1} with some more text to make it longer`}
/>
<ListItemSecondaryAction>
<IconButton aria-label="comments">
<CommentIcon />
</IconButton>
<IconButton edge="end" aria-label="delete">
<DeleteIcon />
</IconButton>
</ListItemSecondaryAction>
</ListItemWithWiderSecondaryAction>
);
})}
</List>
</>
);
}
Below is an equivalent v5 example. The changes compared to the v4 version are:
Uses styled instead of withStyles and makeStyles
Uses ListItemButton instead of the deprecated ListItem button prop
Add disablePadding prop to the ListItem elements. This is needed when leveraging ListItemButton in order to keep the styling equivalent to the v4 example
Package names updated from #material-ui/core and #material-ui/icons to #mui/material and #mui/icons-material
import * as React from "react";
import { styled } from "#mui/material/styles";
import List from "#mui/material/List";
import ListItem from "#mui/material/ListItem";
import ListItemIcon from "#mui/material/ListItemIcon";
import ListItemText from "#mui/material/ListItemText";
import ListItemButton from "#mui/material/ListItemButton";
import ListItemSecondaryAction from "#mui/material/ListItemSecondaryAction";
import Checkbox from "#mui/material/Checkbox";
import IconButton from "#mui/material/IconButton";
import CommentIcon from "#mui/icons-material/Comment";
import DeleteIcon from "#mui/icons-material/Delete";
const StyledList = styled(List)(({ theme }) => ({
width: "100%",
maxWidth: 360,
backgroundColor: theme.palette.background.paper
}));
const ListItemWithWiderSecondaryAction = styled(ListItem)(({ theme }) => ({
"&.MuiListItem-secondaryAction": {
paddingRight: 96
}
}));
export default function CheckboxList() {
const [checked, setChecked] = React.useState([0]);
const handleToggle = (value) => () => {
const currentIndex = checked.indexOf(value);
const newChecked = [...checked];
if (currentIndex === -1) {
newChecked.push(value);
} else {
newChecked.splice(currentIndex, 1);
}
setChecked(newChecked);
};
return (
<>
<StyledList>
{[0, 1].map((value) => {
const labelId = `checkbox-list-label-${value}`;
return (
<ListItem key={value} disablePadding>
<ListItemButton
role={undefined}
dense
onClick={handleToggle(value)}
>
<ListItemIcon>
<Checkbox
edge="start"
checked={checked.indexOf(value) !== -1}
tabIndex={-1}
disableRipple
inputProps={{ "aria-labelledby": labelId }}
/>
</ListItemIcon>
<ListItemText
id={labelId}
primary={`Line item ${
value + 1
} with some more text to make it longer`}
/>
</ListItemButton>
<ListItemSecondaryAction>
<IconButton aria-label="comments">
<CommentIcon />
</IconButton>
<IconButton edge="end" aria-label="delete">
<DeleteIcon />
</IconButton>
</ListItemSecondaryAction>
</ListItem>
);
})}
</StyledList>
<StyledList>
{[2, 3].map((value) => {
const labelId = `checkbox-list-label-${value}`;
return (
<ListItemWithWiderSecondaryAction key={value} disablePadding>
<ListItemButton
role={undefined}
dense
onClick={handleToggle(value)}
>
<ListItemIcon>
<Checkbox
edge="start"
checked={checked.indexOf(value) !== -1}
tabIndex={-1}
disableRipple
inputProps={{ "aria-labelledby": labelId }}
/>
</ListItemIcon>
<ListItemText
id={labelId}
primary={`Line item ${
value + 1
} with some more text to make it longer`}
/>
</ListItemButton>
<ListItemSecondaryAction>
<IconButton aria-label="comments">
<CommentIcon />
</IconButton>
<IconButton edge="end" aria-label="delete">
<DeleteIcon />
</IconButton>
</ListItemSecondaryAction>
</ListItemWithWiderSecondaryAction>
);
})}
</StyledList>
</>
);
}
I removed ListItemSecondaryAction entirely and replaced it with ListItemIcon, so now the code looks something like this:
<ListItem>
<ListItemAvatar>
<Avatar src="image" />
</ListItemAvatar>
<ListItemText primary="name" />
<ListItemIcon>
<IconButton>
<EditIcon />
</IconButton>
</ListItemIcon>
<ListItemIcon>
<IconButton>
<DeleteIcon />
</IconButton>
</ListItemIcon>
</ListItem>

Calling a component gives Cannot read property 'map' of undefined

I made this component, userRow:
userRow:
export default function UserRow(props, {data}) {
const style = styles();
const userList = data.map((row) => {
return { name: row, details: row };
});
return (
<div>
{userList.map(row => (
<List className={style.listSize}>
<ListItem className={style.listSize} >
<ListItemIcon className={style.listSize}>
<PeopleIcon className={style.color}/>
</ListItemIcon>
<ListItemText className={style.text}>{props.userList.name}</ListItemText>
<Link to={`/users/${props.userList.details}`}>
<ListItemIcon className={style.listSize}>
<ListAltIcon className={style.iconColor}/>
</ListItemIcon>
</Link>
</ListItem>
</List>
))}
</div>
)
}
I want to call it in another component, let's say in the users component:
users:
export default function User({ data }) {
const userList = data.map((row) => {
return { name: row, details: row };
});
return (
<div>
<UserRow name={userList} details={userList} />
</div>
)
}
Data is a json:
3) ["Philip J. Fry", "Turanga Leela", "Bender Bending Rodríguez"]
0: "Philip J. Fry"
1: "Turanga Leela"
2: "Bender Bending Rodríguez"
length: 3
__proto__: Array(0)
My problem is i get Cannot read property 'map' of undefined, i tried everything i know.
I want to call the userRow component on the users component and display the data.
I'd do something like this:
export default function UserRow({ name, details }) {
const style = styles();
return (
<ListItem className={style.listSize} >
<ListItemIcon className={style.listSize}>
<PeopleIcon className={style.color}/>
</ListItemIcon>
<ListItemText className={style.text}>{name}</ListItemText>
<Link to={`/users/${details}`}>
<ListItemIcon className={style.listSize}>
<ListAltIcon className={style.iconColor}/>
</ListItemIcon>
</Link>
</ListItem>
)
}
export default function User({ data }) {
// creates the user list here
const userList = data.map((row) => {
return { name: row, details: row };
});
return (
<List className={style.listSize}>
{userList.map(row => (
<UserRow name={row} details={row} />
))}
</List>
)
}
So, have the UserRow component to be JUST the row, not the full list and have the logic of mapping and creates the userList on the parent component/container.
You need to access the props differently since the props are accumulated in the props object:
export default function User({ data }) {
return (
<div>
<List className={style.listSize}>
{
data.map(row => <UserRow name={row} details={row}/>}
}
</List>
</div>
)
}
And access it like this:
export default function UserRow({details}) {
const style = styles();
return (
<ListItem className={style.listSize} >
<ListItemIcon className={style.listSize}>
<PeopleIcon className={style.color}/>
</ListItemIcon>
<ListItemText className={style.text}>{props.name}</ListItemText>
<Link to={`/users/${props.details}`}>
<ListItemIcon className={style.listSize}>
<ListAltIcon className={style.iconColor}/>
</ListItemIcon>
</Link>
</ListItem>
)
}

'Objects are not valid as a React child'

I don't understand why the following error appears.
I'm trying to render {links}, {collapse} in a return function, but it doesn't work.
links and collapse is about opening sub menus.
Thank you for your help.
The error message:
Objects are not valid as a React child (found: object with keys
{$$typeof, type, compare, displayName, muiName}). If you meant to
render a collection of children, use an array instead.
-- Sidebar.js
/*eslint-disable*/
import React from "react";
import classNames from "classnames";
import PropTypes from "prop-types";
import { NavLink } from "react-router-dom";
// #material-ui/core components
import { makeStyles } from "#material-ui/core/styles";
import {
Drawer,
Hidden,
List,
ListItem,
ListItemText,
Icon,
Collapse
} from "#material-ui/core";
import ExpandLess from "#material-ui/icons/ExpandLess";
import ExpandMore from "#material-ui/icons/ExpandMore";
import ListItemLink from "./ListItemLink";
// core components
import AdminNavbarLinks from "components/Navbars/AdminNavbarLinks.js";
import RTLNavbarLinks from "components/Navbars/RTLNavbarLinks.js";
import styles from "assets/jss/material-dashboard-react/components/sidebarStyle.js";
const useStyles = makeStyles(styles);
export default function Sidebar(props) {
const classes = useStyles();
// verifies if routeName is the one active (in browser input)
function activeRoute(routeName) {
return window.location.href.indexOf(routeName) > -1 ? true : false;
}
const { color, logo, image, logoText, routes } = props;
const [open, setOpen] = React.useState(true);
const handleClick = () => {
setOpen(!open);
};
var links = (
<div>
{routes.map((prop, key) => {
return (
<div>
{prop.submenu.length > 0 ? (
<ListItemLink
to={prop.layout + prop.path}
key={prop.id}
menuText={prop.name}
onClick={handleClick}
subOpen={open}
icon={prop.icon}
/>
) : (
<ListItemLink
to={prop.layout + prop.path}
key={prop.id}
menuText={prop.name}
icon={prop.icon}
/>
)}
</div>
);
})}
</div>
);
var collapse = (
<Collapse in={open} timeout="auto" unmountOnExit>
<List component="div" disablePadding>
{routes.map((prop, key) => {
{
prop.submenu.map((sub, index) => {
return (
<ListItemLink
key={sub.id}
to={sub.path}
menuText={sub.name}
icon={sub.icon}
className={classes.nested}
/>
);
});
}
})}
</List>
</Collapse>
);
var brand = (
<div className={classes.logo}>
<a
className={classNames(classes.logoLink, {
[classes.logoLinkRTL]: props.rtlActive
})}
target="_blank"
>
<div className={classes.logoImage}>
<img src={logo} alt="logo" className={classes.img} />
</div>
{logoText}
</a>
</div>
);
return (
<div>
<Hidden mdUp implementation="css">
<Drawer
variant="temporary"
anchor={props.rtlActive ? "left" : "right"}
open={props.open}
classes={{
paper: classNames(classes.drawerPaper, {
[classes.drawerPaperRTL]: props.rtlActive
})
}}
onClose={props.handleDrawerToggle}
ModalProps={{
keepMounted: true // Better open performance on mobile.
}}
>
{brand}
<div className={classes.sidebarWrapper}>
{props.rtlActive ? <RTLNavbarLinks /> : <AdminNavbarLinks />}
<List component="nav" className={classes.list}>
{links}
{collapse}
</List>
</div>
{image !== undefined ? (
<div
className={classes.background}
style={{ backgroundImage: "url(" + image + ")" }}
/>
) : null}
</Drawer>
</Hidden>
<Hidden smDown implementation="css">
<Drawer
anchor={props.rtlActive ? "right" : "left"}
variant="permanent"
open
classes={{
paper: classNames(classes.drawerPaper, {
[classes.drawerPaperRTL]: props.rtlActive
})
}}
>
{brand}
<div className={classes.sidebarWrapper}>
<List component="nav" className={classes.list}>
{links}
{collapse}
</List>
</div>
{image !== undefined ? (
<div
className={classes.background}
style={{ backgroundImage: "url(" + image + ")" }}
/>
) : null}
</Drawer>
</Hidden>
</div>
);
}
Sidebar.propTypes = {
rtlActive: PropTypes.bool,
handleDrawerToggle: PropTypes.func,
bgColor: PropTypes.oneOf(["purple", "blue", "green", "orange", "red"]),
logo: PropTypes.string,
image: PropTypes.string,
logoText: PropTypes.string,
routes: PropTypes.arrayOf(PropTypes.object),
open: PropTypes.bool
};
-- ListItemLink.js
import React from "react";
import { ListItem, ListItemText, ListItemIcon } from "#material-ui/core";
import ExpandLess from "#material-ui/icons/ExpandLess";
import ExpandMore from "#material-ui/icons/ExpandMore";
import { PropTypes } from "prop-types";
import { Link as RouterLink } from "react-router-dom";
function ListItemLink(props) {
const { to, menuText, icon, subOpen, ...other } = props;
return (
<ListItem button component={RouterLink} to={to} {...other}>
<ListItemIcon>{icon}</ListItemIcon>
<ListItemText primary={menuText} />
{subOpen != null ? subOpen ? <ExpandLess /> : <ExpandMore /> : null}
</ListItem>
);
}
ListItemLink.propTypes = {
subOpen: PropTypes.bool,
to: PropTypes.string.isRequired
};
export default ListItemLink;
in collapse, you have two map functions. you should return the second map function.
something like this:
const collapse = (
<Collapse in={open} timeout="auto" unmountOnExit>
<List component="div" disablePadding>
{routes.map((prop, key) => {
return prop.submenu.map((sub, index) => {
return (
<ListItemLink
key={sub.id}
to={sub.path}
menuText={sub.name}
icon={sub.icon}
className={classes.nested}
/>
);
});
})}
</List>
</Collapse>
);
I solved my question as followed:
I guess I returned the wrong object...
<List
{...rest}
className={clsx(classes.root, className)}
>
{pages.map(page => (
<React.Fragment key={page.title}>
<ListItem
className={classes.item}
disableGutters
key={page.title}
onClick={page.submenu.length > 0 ? handleClick : null}
open={page.submenu.length > 0 ? open : null}
>
<Button
activeClassName={classes.active}
className={classes.button}
component={CustomRouterLink}
to={page.href}
>
<div className={classes.icon}>{page.icon}</div>
{page.title}
{page.submenu.length > 0 ? (
open ? (
<ExpandLess />
) : (
<ExpandMore />
)
) : null}
</Button>
</ListItem>
<Collapse in={open} timeout={100} unmountOnExit>
<List component="div" disablePadding>
{page.submenu.map((sub, index) => {
return (
<React.Fragment key={sub.title}>
<ListItem
className={classes.nested}
disableGutters
key={sub.title}
>
<Button
activeClassName={classes.active}
className={classes.button}
component={CustomRouterLink}
to={sub.href}
>
<div className={classes.icon}>{sub.icon}</div>
{sub.title}
</Button>
</ListItem>
</React.Fragment>
);
})}
</List>
</Collapse>
</React.Fragment>
))}
</List>

React: Material-UI - how to style the two item list so items will be next to each other?

I've got a list that consists of two items: 'label' and 'value', this is how it currently looks like:
How I can move items that are on the right side to the left, so they would stay next to the label?
This is my code sample:
<List>
{details.map((item, index) =>
<ListItem key={index} divider alignItems="flex-start">
<ListItemIcon>
<i className={item.icon}/>
</ListItemIcon>
<ListItemText className="br-break" primary={item.label} />
<ListItemSecondaryAction>
<ListItemText className="br-break" primary={item.data}/>
</ListItemSecondaryAction>
</ListItem>
)}
</List>
I've tried to remove <ListItemSecondaryAction> tag - didn't work.
One option is to use material-ui styling to override ListItemText flex value:
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import List from '#material-ui/core/List';
import ListItem from '#material-ui/core/ListItem';
import ListItemIcon from '#material-ui/core/ListItemIcon';
import ListItemText from '#material-ui/core/ListItemText';
const useStyles = makeStyles(theme => ({
root: {
flex: '0.2',
minWidth: '100px'
},
}));
export default function ListDemo() {
const classes = useStyles();
const details = [
{
label: 'Issue Number',
data: 'CCM-1007'
},
{
label: 'Environment',
data: 'TST'
},
{
label: 'Country',
data: 'SE'
},
]
return (
<List>
{details.map((item, index) =>
<ListItem key={index} divider alignItems="flex-start">
<ListItemIcon>
<i className={item.icon} />
</ListItemIcon>
<ListItemText className={classes.root} primary={item.label} />
<ListItemText className={classes.root} primary={item.data} />
</ListItem>
)}
</List>
);
}
Another solution without makeStyles.
import React from "react";
import List from "#material-ui/core/List";
import ListItem from "#material-ui/core/ListItem";
import ListItemIcon from "#material-ui/core/ListItemIcon";
import ListItemText from "#material-ui/core/ListItemText";
export default function ListDemo() {
const details = [
{
label: "Issue Number",
data: "CCM-1007"
},
{
label: "Environment",
data: "TST"
},
{
label: "Country",
data: "SE"
}
];
return (
<List>
{details.map((item, index) => (
<ListItem key={index} divider alignItems="flex-start">
<ListItemIcon>
<i className={item.icon} />
</ListItemIcon>
<ListItemText
primary={item.label}
primaryTypographyProps={{
display: "inline"
}}
secondary={item.data}
secondaryTypographyProps={{
display: "inline"
}}
/>
</ListItem>
))}
</List>
);
}

Categories