So i have a drawer, and ive modified it with a default width of 450px, and a max width 0f 800px. I have xs set 6, and sm set to 4. But it doesnt change. It sets it to 4, and remains, no matter if i expand it to 800, or 450.
<Box>
<Grid container spacing={2} sx={{padding:'20px'}}>
{catalog.map((item, key) => {
return (
<Grid xs={6} sm={4} key={key}>
<Card className="media-catalog-item" sx={{height:'250px'}}>
<CardContent sx={{padding:'0px'}}>
<div className="media-item-title">{item.info.label}</div>
<div onClick={()=>{clickMedia(item)}}>
<img src={"https://example.com" + item.overlay}></img>
<img src={"https://example.com" + item.thumbnail}></img>
</div>
<div className= {list ? "list-item-footer" : "grid-item-footer"}>{item.info.displayName}</div>
</CardContent>
<CardActions>
<Button onClick={() => {notesOperations(item)}}>Notes</Button>
<Button onClick={() => {keywordsOperations(item)}}>Keywords</Button>
</CardActions>
</Card>
</Grid>
)
})}
</Grid>
</Box>
So it should start at 2 items on a row, and as i expand up to 600px+, switch to 3 on a row.
this is using MUI grid v2. Should I just use the regular grid and add item?
You missed to add item property to the Grid
<Box>
<Grid container spacing={2} sx={{padding:'20px'}}>
{catalog.map((item, key) => {
return (
// here you missed the item props
<Grid item xs={6} sm={4} key={key}>
<Card className="media-catalog-item" sx={{height:'250px'}}>
<CardContent sx={{padding:'0px'}}>
<div className="media-item-title">{item.info.label}</div>
<div onClick={()=>{clickMedia(item)}}>
<img src={"https://example.com" + item.overlay}></img>
<img src={"https://example.com" + item.thumbnail}></img>
</div>
<div className= {list ? "list-item-footer" : "grid-item-footer"}>{item.info.displayName}</div>
</CardContent>
<CardActions>
<Button onClick={() => {notesOperations(item)}}>Notes</Button>
<Button onClick={() => {keywordsOperations(item)}}>Keywords</Button>
</CardActions>
</Card>
</Grid>
)
})}
</Grid>
</Box>
Related
const key = '618479acc2ef5ba8018516ac'
function UserPost1 () {
const [post, setPost] = useState(['']);
const handleExpandClick = () => {
setExpanded(!expanded);
};
useEffect(() =>{
axios.get('https://dummyapi.io/data/v1/post' , { headers: { 'app-id': key } })
.then(res => {
setPost(res.data.data)
console.log(res)
})
.catch(err =>{
console.log(err)
})
},[]);
return(
<div className="Post-style">
{post.map(post =>(
<Box sx={{ flexGrow: 1 }}>
<Grid container rowSpacing={0} columnSpacing={{ xs: 1, sm: 2, md: 2, lg: 2 }} >
<Grid
container
direction="row"
justifyContent="center">
<Grid item xs={4} sm={12} md={6} lg={4}>
<div className="card-Style">
<Card sx={{ width: 355}} style={{backgroundColor: "aquamarine"}} >
<CardHeader
avatar={
<Avatar
src={post.owner.picture}
/>
}
action={
<IconButton aria-label="settings">
<MoreVertIcon />
</IconButton>
}
title={post.owner.firstName + " " + post.owner.lastName}
subheader={post.publishDate}
/>
<CardMedia
component="img"
height="194"
image={post.image}
alt="Paella dish"
backgroundcolor="blue"
/>
<CardContent>
<Typography variant="body2" color="text.secondary">
{post.text}
<br></br>
{post.likes}
<br></br>
{post.tags}
</Typography>
</CardContent>
</Card>
</div>
</Grid>
</Grid>
</Grid>
</Box>
))}
</div>
)
}
export default UserPost1;
When im run this code i cant get the data from API using Axios, it says error cannot read properties of undefined (reading 'picture'). I tried to catch the error but it does not show in console log. How do i solve this problem.
should i make the axios to wait until it gets the data API or make it to false.
What should i do, its my first time with API.
Somehow, the picture property is missing inside the owner object.
Add optional chaining before picture:
<CardHeader
avatar={
<Avatar
src={post.owner?.picture}
/>
}
...
Render your post component after complete async query and set state value. Use condition rendering and change default state value from [''] to null.
If your component has a specific height and width, then create a placeholder with the same values.
To exclude layout jumps during query execution, show a placeholder. Show the placeholder while the request is running, and after the request is complete and the value is set to the state, show the post component. Good luck!
// change default useState value
const [post, setPost] = useState(null);
// add condition rendering
{post ? post.map(post => (
<Box sx={{ flexGrow: 1 }}>
<Grid container rowSpacing={0} columnSpacing={{ xs: 1, sm: 2, md: 2, lg: 2 }} >
<Grid
container
direction="row"
justifyContent="center">
<Grid item xs={4} sm={12} md={6} lg={4}>
<div className="card-Style">
<Card sx={{ width: 355 }} style={{ backgroundColor: "aquamarine" }} >
<CardHeader
avatar={
<Avatar
src={post.owner.picture}
/>
}
action={
<IconButton aria-label="settings">
<MoreVertIcon />
</IconButton>
}
title={post.owner.firstName + " " + post.owner.lastName}
subheader={post.publishDate}
/>
<CardMedia
component="img"
height="194"
image={post.image}
alt="Paella dish"
backgroundcolor="blue"
/>
<CardContent>
<Typography variant="body2" color="text.secondary">
{post.text}
<br></br>
{post.likes}
<br></br>
{post.tags}
</Typography>
</CardContent>
</Card>
</div>
</Grid>
</Grid>
</Grid>
</Box>
)) : <div> PLACEHOLDER </div>}
I want to add a date range component in my existing reactjs material ui project.But problem is its taking space instead of just showing it "above other components" just like the Select component
Here's the example snippet I want to add in my app https://codesandbox.io/s/materialui-daterange-picker-2p3f1?file=/src/App.js:274-385
My actual implementation
const Wow = () => (
<DateRangePicker
open={open}
toggle={toggle}
onChange={(range) => setDateRange(range)}
/>
);
const DateRange = () => (
<>
<Grid
container
spacing={1}
>
<Grid
item
lg={10}
md={12}
xl={9}
xs={12}
>
<Button
onClick={() => setOpen(true)}
>
Show
</Button>
<Wow />
</Grid>
<Grid
item
lg={2}
md={12}
xl={9}
xs={12}
>
<Button
variant="contained"
startIcon={<CheckIcon />}
onClick={handleSubmit}
>
Go
</Button>
</Grid>
</Grid>
</>
);
return (
<>
<Helmet>
<title>Selectors | Clever Clicks</title>
</Helmet>
<Box
sx={{
backgroundColor: 'background.default',
minHeight: '100%',
py: 3
}}
>
<Container maxWidth={false}>
<Grid
container
spacing={1}
>
<Grid
item
lg={4}
md={12}
xl={9}
xs={12}
>
<TextField
id="standard-select-currency-native"
select
label="Market"
onChange={handleMarket}
SelectProps={{
native: true,
}}
size="small"
fullWidth
helperText="Please select "
>
{marketplaces.map((option) => (
<option key={option.value} value={option.value}>
{option.label}
</option>
))}
</TextField>
</Grid>
<Grid
item
lg={4}
md={12}
xl={9}
xs={12}
>
<TextField
id="standard-select-currency-native"
select
label="Products"
onChange={handleProduct}
SelectProps={{
native: true
}}
size="small"
fullWidth
helperText="Please select products"
inputProps={{ style: { fontSize: 15, overflow: 'visible' } }}
>
<option value="All"> --All-- </option>
{products.map((option) => (
<option key={option.id} value={`${option.title},${option.seller_sku},${option.id}`}>
{option.title}
</option>
))}
</TextField>
</Grid>
<Grid
item
lg={4}
md={12}
xl={9}
xs={12}
>
<DateRange />
</Grid>
</Grid>
</Container>
</Box>
</>
);
};
Its taking space when button is click to show
if you noticed, the below components are "forced" to stretch. What I want is to make the date range calendars "float".
Any help?
By default, the DateRangePicker component isn't going to have absolute position, which is what you need if you'd like to position the modal without taking up DOM space.
A generic example would be something like this:
.datePicker {
position: absolute;
top: 50px;
left: 50vw;
}
<DateRangePicker
className="datePicker"
open={open}
toggle={toggle}
onChange={(range) => setDateRange(range)}
/>
Using this after modifying the top and left properties to your needs may work if you combine it with a few media queries to compensate for different screen sizes.
However, if you want a more dynamic approach, you can take a look at this answer.
NOTE: Keep in mind that if the parent container is position relative, the absolute positioning will be relative to that element.
I have two buttons and would like to put a space between them. So, I have tried to do that by putting a box around them and then applying a margin to the box. See code below.
render() {
return (
<>
<ThemeProvider theme={theme}>
<CssBaseline />
<BrowserRouter>
<Header />
</BrowserRouter>
</ThemeProvider>
<ThemeProvider theme={theme}>
<Grid container justify="center">
<Box pt={3}>
<Paper>
<Box pl={3} pr={3} pb={3} pt={3}>
<Grid container spacing={0}>
<Grid item xs={6}>
<Typography
variant="h6"
gutterBottom={false}
onClick={this.handleSetDummyText}
>
Keyword Processor
</Typography>
</Grid>
<Grid item xs={6}>
{/* ********* Offending code section ********** */}
<Button
color={
this.state.sorttypeStatus === 'default'
? 'primary'
: 'secondary'
}
onClick={this.handleSortDefault}
>
DEFAULT
</Button>
{/* ********* Offending code section ********** */}
<Button
color={
this.state.sorttypeStatus === 'alpha'
? 'primary'
: 'secondary'
}
onClick={this.handleSortAlpha}
>
A-Z
</Button>
<Button
color={
this.state.sorttypeStatus === 'length'
? 'primary'
: 'secondary'
}
onClick={this.handleSortLength}
>
LENGTH
</Button>
</Grid>
<Grid container spacing={2}>
<Grid item xs={6}>
<TextField
label="Input Keywords"
fullWidth
multiline
rows={10}
variant="outlined"
margin="normal"
onChange={this.handleInputText}
// defaultValue={defaultInputText}
value={this.state.inputText}
/>
<Box m={1}>
<Button
variant="contained"
color="primary"
onClick={this.inputToOutput}
>
Parse
</Button>
<Button
variant="outlined"
color="secondary"
onClick={this.clearInput}
// default={this.state.inputText}
>
Clear
</Button>
</Box>
<br />
<Checkboxes
handleDedupe={this.handleDedupe}
handleRemoveNumbers={this.handleRemoveNumbers}
handleConvertToLowercase={
this.handleConvertToLowercase
}
handleOneWordPerLine={this.handleOneWordPerLine}
handleAddCommas={this.handleAddCommas}
handleAddCommasSpace={this.handleAddCommasSpace}
handleStartWords={this.handleStartWords}
handleEndWords={this.handleEndWords}
/>
</Grid>
<Grid item xs={6}>
<TextField
label="Output Keywords"
fullWidth
multiline
rows={30}
variant="outlined"
margin="normal"
value={this.state.outputText}
/>
<Button
variant="contained"
color="primary"
mt={5}
onClick={() => {
navigator.clipboard.writeText(
this.state.outputText
);
}}
>
Copy
</Button>
<Button
variant="outlined"
color="secondary"
mt={5}
onClick={this.clearOutput}
>
Clear
</Button>
<Button
variant="outlined"
color="secondary"
mt={5}
onClick={this.handleSetDummyText}
>
Dummy Data
</Button>
</Grid>
</Grid>
</Grid>
</Box>
</Paper>
</Box>
</Grid>
</ThemeProvider>
</>
);
}
}
But the boxes seem to stick together like glue! I do have a custom theme but I cannot seem to get that to work with my App.js file because I am using a class component, rather than a functional component. I understand that you are supposed to use withStyles with class components, but I have struggled to get that to work. So, as a fix, I am trying the Box method.
Any idea how to get my box method to work?
you could use Grid component of material ui and as justify content use space-between
<Grid
style={{width:'140px'}}
container
direction="row"
justify="space-between"
alignItems="center">
<Button/>// here are the buttons
<Button/>
</Grid>
read more about the Grid https://material-ui.com/components/grid/
or you could do it with <div/> i used inline style so that you can read it
easier
<div style ={{ width:'200px',
display:'flex',
flexDirection:'row',
justifyContent:'space-between'
}}>
<button>button 1</button>
<button>button 2</button>
</div>
see working examples with div https://codesandbox.io/s/youthful-taussig-jyesc?file=/src/App.js:67-263
Have you tried to put each button in a box?
<div>
<Box m={1}>
<Button variant="contained">one</Button>
</Box>
<Box m={1}>
<Button variant="contained">two</Button>
</Box>
</div>
The <Box> component works like a <div>, it is a block, so your code can not align buttons in a row.
You can use flex-box to style to get what you want. Use Grid item, container and spacing API of Grid fit your need as well.
Below is an example:
<Grid container spacing={4}>
<Grid item xs={2}>
<Button fullWidth variant="contained" color="primary">
button A{" "}
</Button>
</Grid>
<Grid item xs={2}>
<Button fullWidth variant="contained" color="primary">
button B{" "}
</Button>
</Grid>
</Grid>
When using <Grid container>, you create a flex-box container. By default on ReactJS, the flex-items inside will be aligned by row. That's the reason why We do not have to declare props direction="row" on the container.
You can change the spacing value to change the space between two Grid items. By default, 1 = 8px and it can be customized in material ui as well.
xs indicates the size of your screen, in material ui we have 5 of them xs, sm, md, lg and xl, you can read about it in material ui docs.
fullWidth buttons just to make the buttons take the whole width of containers for ease of seeing space between buttons.
Working example on codesandbox: https://codesandbox.io/s/angry-wescoff-lnj71?file=/src/App.js
I am new to reactjs. I need to check whether if records are present, then I need to show grid using map function. Else I need to show message "No data". This is my code. I used ternary operator to do so
<Grid container spacing={2}>
{data.length > 0 ?
{data.map((activity) => (
<Grid
item
xs={6}
sm={4}
md={3}
lg={3}
onClick={() => {
setSpec(activity.spec)
setActivity(activity)
handleClickOpen(activity.spec)
}}
className={classes.thumbMain}
>
<ButtonBase focusRipple className={classes.fullwidthBtn}>
<Card className={classes.manage}>
<Box mt={2} mb={1}>
<Box
className={classes.mainIcons}
></Box>
</Box>
<Typography className={classes.cardlabel}>{(activity.name)}</Typography>
</Card>
</ButtonBase>
</Grid>
))}
: <p>No data</p>
}
</Grid>
The above code returns following error
Parsing error: ',' expected : in data.map((activity)
You shouldn't wrap data.map(...) in braces:
<Grid container spacing={2}>
{data.length ? (
data.map((activity) => (
<Grid
item
xs={6}
sm={4}
md={3}
lg={3}
onClick={() => {
setSpec(activity.spec);
setActivity(activity);
handleClickOpen(activity.spec);
}}
className={classes.thumbMain}
>
<ButtonBase focusRipple className={classes.fullwidthBtn}>
<Card className={classes.manage}>
<Box mt={2} mb={1}>
<Box className={classes.mainIcons}></Box>
</Box>
<Typography className={classes.cardlabel}>
{activity.name}
</Typography>
</Card>
</ButtonBase>
</Grid>
))
) : (
<p>No data</p>
)}
</Grid>;
You should wrap JS code in braces only one time to use it in JSX. If you add braces in other braces then you will be getting that error again.
I am using material ui in react and after building the modals it loads only the last element of the object array.
<Grid container className={classes.root} spacing={2}>
<Grid item xs={12}>
<Grid container justify="center" spacing={spacing}>
{Object.keys(props.listOfAndis).map((keyName, i) => (
<Grid item>
<Card className={classes.card}>
<CardContent>
<Typography>Word of the Day {i}</Typography>
<Typography>be{bull}nev{bull}o{bull}lent</Typography>
<Typography>adjective</Typography>
<Typography>well meaning and kindly.<br/>{'"a benevolent smile"'}</Typography>
</CardContent>
<CardActions>
<div>
<Button size="small" onClick={handleOpen}>View Profile</Button>
</div>
<Modal
aria-labelledby="simple-modal-title"
aria-describedby="simple-modal-description"
open={open}
onClose={handleClose}>
<div style={modalStyle} className={classes.paper}>
<IconButton onClick={handleClose} tooltip="Close"
style={pointer && topRight}> X </IconButton>
<h2 id="simple-modal-title">Current
Project: {props.listOfAndis[keyName].currentProject}</h2>
<p id="simple-modal-description">Name: {props.listOfAndis[keyName].name}</p>
<p id="simple-modal-description">E-mail: {props.listOfAndis[keyName].emailAddress}</p>
<p id="simple-modal-description">Skills: {props.listOfAndis[keyName].skills}</p>
</div>
</Modal>
</CardActions>
</Card>
</Grid>
))}
</Grid>
</Grid>
</Grid>
Currently I have 3 mock entries, but only the last one is used for all three modals.
I have tried using key={i} with no success. What am I doing wrong?