I have an array of strings like this:
const checkboxItems = [
'a', 'b', 'c',
'd', 'e', 'f',
'g', 'h', 'i',
]
and I want to populate three columns by the column order, so the output will be:
a d g
b e h
c f i
I have a wrapper component with css like this:
const CheckboxWrapper = styled('div')`
display: grid;
grid-template-columns: 1fr 1fr 1fr;
`;
and I need to render checkbox components in three columns with labels from checkboxItems
. My component looks like this:
<CheckboxWrapper>
{
checkboxItems.map(item => {
return <Checkbox
key={'checkBox'}
checked={false}
onClick={() => { }}
>
<Label>{item}</Label>
</Checkbox>
})
}
</CheckboxWrapper>
Note that my current code renders items on this way:
a b c
d e f
g h i
What am I doing wrong? An example will be appreciated!
As you .map()
over checkboxItems
they're getting rendered in the order of appearance, whereas you need to render them transposed.
To get desired result, general approach would be to break your source array into chunks of length 3 (the number of columns), transposed according to desired order:
itemsToRender = Array(Math.ceil(checkboxItems.length/3))
.fill()
.map((_, i, s) =>
Array(3)
.fill()
.map((_,j) =>
checkboxItems[i+j*s.length]))
Following is a live demo of that approach:
const { render } = ReactDOM,
rootNode = document.getElementById('root')
const App = () => {
const checkboxItems = ['First name','Last name','Email','Phone','Address','Gender','City','Postcode','Country/State','Country','Lifetime value','Tickets in period','Revenue in period','Permission to contact','Customer ID','Account ID','AS Customer tags','Product/Event','Price Category','Section','Row','Seat'],
itemsToRender = Array(Math.ceil(checkboxItems.length/3))
.fill()
.map((_, i, s) =>
Array(3)
.fill()
.map((_,j) =>
checkboxItems[i+j*s.length]))
return (
<div className="wrapper">
{
itemsToRender.map((row, rowIdx) => (
<div key={rowIdx} className="row">
{
row.map((item, itemPos) => item && (
<label key={itemPos} className="cell">
<input type="checkbox" value={item} />
{item}
</label>
))
}
</div>
))
}
</div>
)
}
render (
<App />,
rootNode
)
.wrapper {
display: flex;
flex-direction: column;
}
.row {
display: flex;
flex-direction: row;
}
.cell {
width: 150px;
height: 50px;
margin: 5px;
background-color: cadetblue;
color: #fff;
display: flex;
align-items: center;
justify-content: flex-start;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script><div id="root"></div>
Another approach (to proceed with grid
layout and rearrange items, using CSS and repeat()
function in particular) is to make use of Material-UI styling (which is the case here) and set grid-template-rows
dynamically, based on the number of rows it will take to wrap your list:
const { render } = ReactDOM,
{ FormControlLabel, Checkbox } = MaterialUI,
{ makeStyles } = MaterialUI
const rootNode = document.getElementById('root')
const useStyles = rowNum => makeStyles({
wrapper: {
display: 'grid',
gridTemplateRows: `repeat(${rowNum}, 1fr)`,
gridAutoFlow: 'column'
}
})
const App = () => {
const checkboxItems = ['First name','Last name','Email','Phone','Address','Gender','City','Postcode','Country/State','Country','Lifetime value','Tickets in period','Revenue in period','Permission to contact','Customer ID','Account ID','AS Customer tags','Product/Event','Price Category','Section','Row','Seat'],
classes = useStyles(Math.ceil(checkboxItems.length/3))()
return(
<div className={classes.wrapper}>
{
checkboxItems.map((item, itemIdx) => (
<FormControlLabel
key={itemIdx}
control={
<Checkbox
name={item}
/>
}
label={item}
/>
))
}
</div>
)
}
render (
<App />,
rootNode
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script><script src="https://unpkg.com/@material-ui/core@latest/umd/material-ui.development.js"></script><div id="root"></div>