How to show array elements in List Item Text - javascript

I am new to react. I am using ListIemText to show values in the screen. My question is how do I use List Item text to show all the elements of an array in a list.
Here is the code. Kpi_Before is the array element.
<MuiThemeProvider theme={theme}>
<React.Fragment>
<AppBar size>Confirm Information</AppBar>
<br />
<br />
<List>
<ListItemText primary="Title" secondary={Title} />
<ListItemText
primary="Details of Best Practice"
secondary={Details}
/>
<ListItemText
primary="What is the Best Practice"
secondary={What}
/>
<ListItemText
primary="Why was the Best Practice Implemented"
secondary={Why}
/>
<ListItemText
primary="How was the Best Practice Implemented"
secondary={How}
/>
<ListItemText primary="Implementation Status" secondary={Status} />
<ListItemText primary="Cost of Implementation" secondary={Cost} />
<ListItemText
primary="Benefits of the Best Practice"
secondary={Benefits}
/>
<ListItemText
primary="Time taken for Implementation"
secondary={Time}
/>
<ListItemText
key={idx}
primary="KPI Before Implementation"
secondary={Kpi_Before}
/>
<ListItemText primary="UOM_Before" secondary={UOM_Before} />
<ListItemText primary="Base_Before" secondary={Base_Before} />
<ListItemText primary="Base_Before" secondary={Target_Before} />
<ListItemText primary="Target Date" secondary={dateTime} />
</List>
</React.Fragment>
</MuiThemeProvider>

If I'm understanding what you're wanting. You could do something like:
<div>
<ul>{Kpi_Before.map(item => <li key={item}> {item} </li>)}</ul>
</div>
This will iterate through the Kpi_Before array. When using .map in React you should have a key for every item so that you need to reference it to remove it using .filter or some other method, React can find it. If for some reason you have equal values in the array you could do something like this instead:
<div>
<ul>{Kpi_Before.map(item => <li key=Date.now()> {item} </li>)}</ul>
</div>

Related

how to render component from .map() in react

So im trying to not duplicate code and probably over complicating this but im very curious if there is a way for a system like this to work
<Drawer anchor="right" open={sideBarOpen} onClose={toggleSideBar}>
<List className={classes.sideBar}>
{[
["test1", <LockOpenIcon />],
["test2", <LockOpenIcon />],
["test2", <LockOpenIcon />],
].map(({ text, icon }, index) => (
<Fragment key={index}>
<ListItem button>
<ListItemIcon>{icon}</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
<Divider />
</Fragment>
))}
</List>
</Drawer
where I map over an array of pairs of [text, iconComponent] and then render the iconComponent in the following element. this is producing no errors (but also not rendering anything in the ) and if theres not a way then thats cool but any help would be appreciated.
Yes, it's possible, and you've mostly done it right. You just used object destructuring ({text, icon}) where you should have used iterable destructuring ([text, icon]):
<Drawer anchor="right" open={sideBarOpen} onClose={toggleSideBar}>
<List className={classes.sideBar}>
{[
["test1", <LockOpenIcon />],
["test2", <LockOpenIcon />],
["test2", <LockOpenIcon />],
].map(([ text, icon ], index) => (
<Fragment key={index}>
<ListItem button>
<ListItemIcon>{icon}</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
<Divider />
</Fragment>
))}
</List>
</Drawer>
However, if the values are hardcoded like that, you might consider abstracting the repeated part of that into its own component:
const MyListItem = React.memo(({text, icon}) => (
<ListItem button>
<ListItemIcon>{icon}</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
));
(The React.memo is just because I figure this doesn't change unless text or icon changes.)
Then it's:
<Drawer anchor="right" open={sideBarOpen} onClose={toggleSideBar}>
<List className={classes.sideBar}>
<MyListItem text="test1" icon={<LockopenIcon/>} />
<Divider />
<MyListItem text="test2" icon={<LockopenIcon/>} />
<Divider />
<MyListItem text="test3" icon={<LockopenIcon/>} />
</List>
</Drawer>

Adjacent JSX elements must be wrapped in an enclosing tag error, when it wrapped in a closing tag

return (
<form className={classes.root} noValidate autoComplete="off">
{Object.keys(fields).map(key => (
<FormControl key={key} className={classes.formControl}>
<TextField className={classes.textField} value={fields[key].type} />
<IconButton
aria-label={`Remove ${fields[key].type} field`}
className={classes.button}
onClick={() => deleteField(value, key, onChange)}
>
<ClearIcon />
</IconButton>
</FormControl>
<div></div>
))}
</form>
);
Anything entered after the FormControl gives me this error, be it this example div or anything more complex. I can render anything inside the FormControl tags, but the moment it's moved out or anything else outside of them gets this error.
Assuming that the <div></div> segment after the <FormControl /> is there for a reason, you will need to wrap the return with React Fragments. This is used to group the elements within the Array.map() callback
{Object.keys(fields).map(key => (
<>
<FormControl key={key} className={classes.formControl}>
<TextField className={classes.textField} value={fields[key].type} />
<IconButton
aria-label={`Remove ${fields[key].type} field`}
className={classes.button}
onClick={() => deleteField(value, key, onChange)}
>
<ClearIcon />
</IconButton>
</FormControl>
<div></div>
</>
))}
I think you should remove <div></div> from after <FormControl />. And your code will work perfectly fine.

Render component inside Tabs after .map function return

When I try to render TabPane inside a .map function I have the following issue: my component (DepartmentView) is rendered just for the first TabPane, for the next TabPane content is empty.
I am using ANT Design library.
My question is how can I render DepartmentView for each TabPane from the .map function?
<Tabs tabPosition="left" className="tab-view-page">
{
data.map((item) => (
<TabPane
tab={(
<CustomTabTitle
title={item.name}
subtitle=""
/>
)}
key={item.id}
>
<DepartmentView data={item} />
</TabPane>
))
}
</Tabs>
DepartmentView component:
<div className="main-section">
<div className="horizontal-tabs-container">
<Tabs className="horizontal-tabs-profile">
<TabPane tab={<FormattedHTMLMessage id="layout.tabs.overview" />} key="overview">
Here will be overview page
</TabPane>
<TabPane tab={<FormattedHTMLMessage id="layout.tabs.staff" />} key="staff">
<Employees />
</TabPane>
<TabPane tab={<FormattedHTMLMessage id="layout.tabs.settings" />} key="settings">
<Settings />
</TabPane>
</Tabs>
</div>
</div>
Please, check that you've imported antd css.
import "antd/dist/antd.css";
I don't see any syntax errors. Maybe you could check that the data array is greater than 1 in length and that each item object has all required keys.

Returning nightmare with .map() inside of a .map()

I've been at this for a while. So I have some nested navigation json that I am using. The top level navigation is loading fine (the nav.map) once I move further down the rabbit hole I find myself not returning the top level or the sub level navigation. Everything compiles successfully. Am I just missing it?
return(
<List component="nav" className={classes.root}>
{nav.map(function(element) {
<ListItem
button
onClick={handleClick}
id={element.toplevel}
key={element.toplevel}
>
<ListItemText primary={element.toplevel} />
{open ? <ExpandLess /> : <ExpandMore />}
</ListItem>;
return element.children.map(function(child) {
return (
<Collapse timeout="auto" unmountOnExit>
<List component="div" disablePadding>
<ListItem button className={classes.nested}>
<ListItemIcon>
<StarBorder />
</ListItemIcon>
<ListItemText primary={child.name} />
</ListItem>
</List>
</Collapse>
);
});
})}
</List>
);
Make sure that your map callback functions actually return the jsx code. Your return statements are not set right.
One way that is commonly used in react-land to make the jsx code more readable is the arrow function syntax. This way you get rid of the return statements and return the whole function body (it's just syntactic sugar).
Next thing: be aware of your closing tags. I just assumed that your list item of the element object closes after the ListItemText tag and that your second map function opens a new list item after your element ListItem. jsx only lets you return one root tag at a time. This is why (as the comment below has suggested) using an empty <> ... </> tag pair as a root element will solve this issue.
return (
<List component="nav" className={classes.root}>
{data.nav.map((element) => (
<>
<ListItem
button
onClick={handleClick}
id={element.toplevel}
key={element.toplevel}
>
<ListItemText primary={element.toplevel} />
{open ? <ExpandLess /> : <ExpandMore />}
</ListItem>
{
element.children.map((child) => (
<Collapse timeout="auto" unmountOnExit>
<List component="div" disablePadding>
<ListItem button className={classes.nested}>
<ListItemIcon>
<StarBorder />
</ListItemIcon>
<ListItemText primary={child.name} />
</ListItem>
</List>
</Collapse>
))
}
</>
))}
</List>
);
Sandbox link: https://codesandbox.io/s/material-demo-uv7c7?fontsize=14&hidenavigation=1&theme=dark
Try this, i have restructured it a bit.
<List component="nav" className={classes.root}>
{nav.map(function(element) {
return(
<ListItem
button
onClick={handleClick}
id={element.toplevel}
key={element.toplevel}
>
<ListItemText primary={element.toplevel} />
{open ? <ExpandLess /> : <ExpandMore />}
</ListItem>
{element.children.map(function(child) {
return (
<Collapse timeout="auto" unmountOnExit>
<List component="div" disablePadding>
<ListItem button className={classes.nested}>
<ListItemIcon>
<StarBorder />
</ListItemIcon>
<ListItemText primary={child.name} />
</ListItem>
</List>
</Collapse>
)
})
}
}))}
</List>
);

How to avoid DRY code with React Components

Currently Using React with Material UI v1.0 in implementing a list but I don't want to repeat my code.
The existing Code looks like this.
import List from 'material-ui/List';
import DashboardIcon from 'material-ui-icons/Dashboard';
import BuildIcon from 'material-ui-icons/Build';
import Listings from './BarComponents';
function SideBar() {
return (
<div>
<List>
<ListItem button>
<ListItemIcon>
<DashboardIcon />
</ListItemIcon>
<ListItemText primary="Dashboard" />
</ListItem>
<ListItem button>
<ListItemIcon>
<BuildIcon />
</ListItemIcon>
<ListItemText primary="Control Panel" />
</ListItem>
</List>
</div>
);
}
export default SideBar;
I want to get avoid repeating creating the list items so i've created a new file and passed the props into, code is below.
import React from 'react'
import { ListItem, ListItemIcon, ListItemText } from 'material-ui/List';
export default function Listings(props) {
return(
<div>
<ListItem button>
<ListItemIcon>
<props.icon />
</ListItemIcon>
<ListItemText primary={props.prim} />
</ListItem>
</div>
);
}
And also this
<Listings icon={DashboardIcon} prim="Dashboard" />
<Listings icon={BuildIcon} prim="Build" />
Into the original file for a replacement of
<ListItem button>
<ListItemIcon>
<DashboardIcon />
</ListItemIcon>
<ListItemText primary="Dashboard" />
</ListItem>
<ListItem button>
<ListItemIcon>
<BuildIcon />
</ListItemIcon>
<ListItemText primary="Control Panel" />
</ListItem>
Is the best way to pass a component e.g though
and call it via Thanks in advance.
You can use a dynamic component.
renderElement(name, props = {}) {
var MyComponent = name
return <MyComponent {...props} />;
}
render() {
return(
<div>
<ListItem v-for="item in list" key={item.id} button={item.button}>
<ListItemIcon>
{renderElement(props.icon)}
</ListItemIcon>
<ListItemText primary={props.prim} />
</ListItem>
</div>
);
}

Categories

Resources