I currently have a table using a slider to provide additional details for a table. When the slider component opens I have an X to close to the slider. I am attempting to have that X close the slider and have the table in its original form appear.
Here is a code sandbox:
code sandbox
Slider component :
function ExpandToggle(isOpenProps) {
const [isOpen, setIsOpen] = useState(false);
const toggle = () => {
setIsOpen(!isOpen);
};
return (
<>
<Button>
<ArrowForwardIosIcon size="small" onClick={toggle} />{" "}
</Button>
<SliderInfo open={isOpen} />
</>
);
}
SliderInfo component with onClick={open=false}
export default function SliderInfo({ open }) {
const classes = useStyles();
return (
<Slide direction="left" in={open} mountOnEnter unmountOnExit>
<div className={classes.root}>
<Grid container>
<Grid item>
<Typography variant="h6">Vanila Ice Cream</Typography>
</Grid>
<Grid item>
<Typography variant="h6">Chocolate Ice Cream</Typography>
</Grid>
<Grid item>
<Typography variant="h6">Strawberry Ice Cream</Typography>
</Grid>
<Grid item>
<Typography variant="h6">Sherbert </Typography>
</Grid>
<Grid item>
<Typography variant="h6">None</Typography>
</Grid>
<Grid item>
<Button>
<CloseIcon onClick={open=false} />
</Button>
</Grid>
</Grid>
</div>
</Slide>
On CloseIcon I have an onClick that i'm trying to set open which is passed from Slider to false so it can close the slider component. At the moment upon clicking on the CloseIcon it is not do anything.
Don't modify props directly.
Pass in the toggle function just like you passed in the open variable, and call it instead.
<SliderInfo open={isOpen} toggleOpen={toggle} />
// In Sliderinfo
export default function SliderInfo({ open, toggleOpen }) {
...
<CloseIcon onClick={toggleOpen} />
If your toggle doesn't serve the same purpose, create a new function that only sets isOpen to false and use it instead.
Also remember that onClick expects a function. So the open=false is actually getting executed during render, not after a click. Correct inline format would be onClick={(e) => {//do stuff}}.
You can pass a callback function to the Slider that can call your setIsOpen state modifier, and then pass it to onClick:
function ExpandToggle(isOpenProps) {
const [isOpen, setIsOpen] = useState(false);
const toggle = () => {
setIsOpen(!isOpen);
};
return (
<>
<Button>
<ArrowForwardIosIcon size="small" onClick={toggle} />{" "}
</Button>
<SliderInfo open={isOpen} onRequestClose={() => { setIsOpen(false) }} />
</>
);
}
export default function SliderInfo({ open, onRequestClose }) {
const classes = useStyles();
return (
<Slide direction="left" in={open} mountOnEnter unmountOnExit>
<div className={classes.root}>
<Grid container>
<Grid item>
<Typography variant="h6">Vanila Ice Cream</Typography>
</Grid>
<Grid item>
<Typography variant="h6">Chocolate Ice Cream</Typography>
</Grid>
<Grid item>
<Typography variant="h6">Strawberry Ice Cream</Typography>
</Grid>
<Grid item>
<Typography variant="h6">Sherbert </Typography>
</Grid>
<Grid item>
<Typography variant="h6">None</Typography>
</Grid>
<Grid item>
<Button>
<CloseIcon onClick={onRequestClose} />
</Button>
</Grid>
</Grid>
</div>
</Slide>
Related
Can someone help me in solving this error.
I am unable to rectify this error.
this is what i got in the browser's console
const Cart = ({ cart }) => {
const classes = useStyles();
const EmptyCart = () => (
<Typography variant="subtitle1">
You have no items in your cart, start adding some!!!
</Typography>
);
const FilledCart = () => (
<>
<Grid container spacing={3}>
{cart.line_items.map((item) => (
<Grid item xs={12} sm={4} key={item.id}>
<CartItem item={ item }/>
</Grid>
))}
</Grid>
<div className={classes.cardDetails}>
<Typography variant='h4'>
Subtotal: {cart.subtotal.formatted_with_symbol}
</Typography>
<Button className={classes.emptyButton} size="large" type="button" variant="contained" color="secondary">Empty cart</Button>
<Button className={classes.checkoutButton} size="large" type="button" variant="contained" color="primary">Checkout</Button>
</div>
</>
)
if (!cart.line_items)
return '.......loading';
return (<Container>
<div className={classes.toolbar} />
<Typography className={classes.title} variant='h3' gutterBottom>
Your Shopping Cart
</Typography>
{!cart.line_items.length ? <EmptyCart /> : <FilledCart />}
</Container>);
};
export default Cart;
Note that The prop justify is deprecated, use justifyContent instead.
So, replace justify by justifyContent.
Before :
<Grid container **justify="space-between"** alignItems="center" spacing={4}>
After:
<Grid container **justifyContent="space-between"** alignItems="center" spacing={4}>
I was checked official document but no luck, after that I did custom styling in following way and it work fine for me.
Error:
<Grid
container
direction="row"
justifyContent="center"
alignItems="center"
>
Solution:
<Grid
container
direction="row"
style={{justifyContent:"center"}}
alignItems="center"
>
I'm having an issue with the latest version of Mui. I'm using a Theme to change the default styling of a text field input the error code has something to do with "./node_modules/#mui/material/FormLabel/FormLabel.js/FormLabelRoot<" I've got the following dependencies
"#emotion/react": "^11.4.1",
"#emotion/styled": "^11.3.0",
"#mui/icons-material": "^5.0.1",
"#mui/material": "^5.0.1",
If anyone has an idea I'd love to hear it :)
import React, { useState } from "react"
import { Button, createTheme, Grid, TextField, Tooltip } from "#mui/material"
import { ThemeProvider } from "#mui/system"
import { AddRounded, CalendarToday, Phone, Email, SearchOutlined, People, Work } from "#mui/icons-material"
import { orange } from "#mui/material/colors"
function App() {
//logic
const [contacts, setContacts] = useState([])
const [addFormData, setAddFormData] = useState({
name: "", email: "", phone: "", dateCreated: "", area: ""
})
/* search reflects the value of the googleesque, search bar. */
const [search, setSearch] = useState("")
/* refrlcts the */
const [searchResults, setSearchResults] = useState([])
const handleAddFormChange = (e) => {
e.preventDefault()
const fieldName = e.target.getAttribute("name")
console.log(fieldName)
let fieldValue = e.target.value
console.log(fieldValue)
const newFormData = { ...addFormData }
newFormData[fieldName] = fieldValue
setAddFormData(newFormData)
}
const handleAddFormSubmit = (e) => {
e.preventDefault()
const newContact = {
name: addFormData.name,
email: addFormData.email,
phone: addFormData.phone,
dateCreated: addFormData.dateCreated,
area: addFormData.area,
split: addFormData.split
}
const newContacts = [...contacts, newContact]
setContacts(newContacts)
}
const handleSearch = (e) => {
e.preventDefault()
setSearch(e.target.value)
if (search !== "") {
const newContactList = contacts.filter((contact) => {
console.log(Object.values(contact).join(" ").toLowerCase())
return Object.values(contact).join(" ").toLowerCase().includes(search.toLowerCase())
})
console.log(search)
console.log(Object.values(contacts).join(" ").toLowerCase())
setSearchResults(newContactList)
} else {
setSearchResults(contacts)
}
}
const theme = createTheme({
palette: {
primary: {
// Purple and green play nicely together.
main: orange[500],
},
},
});
return (
<>
<ThemeProvider theme={theme}>
<Grid container spacing={1} alignItems="center" >
<Grid item>
<SearchOutlined />
</Grid>
<Grid item style={{ marginBottom: "15px", marginTop: "15px" }} >
<TextField type="text" variant="outlined" label="Search" onChange={handleSearch} />
</Grid>
</Grid>
<div >
{/* Main Container with soacing between pairs set to (3) */}
<Grid container spacing={3} >
{/* First pair, people icon + name input */}
<Grid item>
<Grid container spacing={1} alignItems="center">
<Grid item>
{/* icon */}
<Tooltip title="Name" placement="bottom" arrow>
<People />
</Tooltip>
</Grid>
<Grid item>
{/* input */}
<TextField label="Name" variant="outlined" id="name" name="name" type="text" onChange={handleAddFormChange} />
</Grid>
</Grid>
</Grid>
{/* Second pair */}
<Grid item>
<Grid container spacing={1} alignItems="center">
<Grid item>
{/* icon */}
<Tooltip title="what's your name" placement="bottom" arrow>
<Work />
</Tooltip>
</Grid>
<Grid item>
{/* Input */}
<TextField label="Area" variant="outlined" color="colME" id="area" name="area" type="text" onChange={handleAddFormChange} />
</Grid>
</Grid>
</Grid>
{/* Third Pair */}
<Grid item>
<Grid container spacing={1} alignItems="center">
<Grid item>
{/* Icon */}
<Tooltip title="name#example.com" placement="bottom" arrow>
<Email />
</Tooltip>
</Grid>
<Grid item>
{/* input */}
<TextField label="Email" variant="outlined" id="email" name="email" type="text" onChange={handleAddFormChange} />
</Grid>
</Grid>
</Grid>
<Grid item>
<Grid container spacing={1} alignItems="center">
<Grid item>
{/* Icon */}
<Tooltip title="Ex:(0049)15208513630" placement="bottom" arrow>
<Phone />
</Tooltip>
</Grid>
<Grid item>
{/* Input */}
<TextField label="phone" variant="outlined" id="dateCreated" name="phone" type="text" onChange={handleAddFormChange} />
</Grid>
</Grid>
</Grid>
<Grid item>
<Grid container spacing={1} alignItems="center">
<Grid item>
{/* Icon */}
<Tooltip title="Format:dd/mm/yyyy" placement="bottom" arrow>
<CalendarToday />
</Tooltip>
</Grid>
<Grid item>
{/* Input */}
<TextField label="Date" variant="outlined" id="dateCreated" name="dateCreated" type="text" onChange={handleAddFormChange} />
</Grid>
</Grid>
</Grid>
</Grid>
<Button style={{ marginBottom: "15px", marginTop: "15px", }} onClick={handleAddFormSubmit} variant="contained" startIcon={<AddRounded />}>
Add
</Button>
</div>
</ThemeProvider>
{/* if there less than 1 character in the search bar render the normal contacts, if not render only the contacts that match the search input... */}
{/* <ContactList contacts={search.length < 1 ? contacts : searchResults} key={contacts.id} /> */}
</>
);
}
export default App;
OP solved their problem, but for those like me that had a similar issue, be sure to check these few things. I'm experiencing these issues since I've upgraded our code-base to the latest version of Material UI.
The issue appears when you use a color or variant prop value not supported in a given component, usually Button, IconButton, or TextField.
Previously color="default" was just fine, but I realized that default was no longer supported. It's current equivalent is inherit.
If you want to support a custom color, you can create a theme that supports that. Read here: Adding new colors (mui.com)
This post has been resolved
Hi, I'm using Material-UI in my React App, and I want to centre a Grid item that contains a Card and two more Grid items.
Here is the relevant code. The Cards do appear in the middle of the screen, but they aren't centred and it's really, really annoying me.
Screenshot:
Necessary code:
render() {
return (
<Grid container>
<Grid item xs={12}>
<Typography variant="h3" gutterBottom>
My Projects
</Typography>
</Grid>
<Grid item xs={6} justify="center">
<Grid item xs={12}>
<Card>
<CardMedia
component="img"
height="140"
image="https://github.com/dbarnes18/Portfolio/blob/master/assets/images/spotter.png?raw=true"
alt="Spotter"
/>
<CardContent>
<Typography gutterBottom variant="h5" component="div">
Spotter
</Typography>
<Typography variant="body2" color="text.secondary">
Spotter is an easy-to-use Spotify music controller with
functioning room and voting systems.
</Typography>
</CardContent>
<CardActions>
<Button
size="small"
color="primary"
to="/project/spotter"
component={Link}
>
Read More
</Button>
</CardActions>
</Card>
</Grid>
<Grid item xs={12}>
<br />
</Grid>
<Grid item xs={12}>
<Card>
<CardMedia
component="img"
height="140"
image="https://github.com/dbarnes18/Portfolio/blob/master/assets/images/impulse.png?raw=true"
alt="Spotter"
/>
<CardContent>
<Typography gutterBottom variant="h5" component="div">
Impulse
</Typography>
<Typography variant="body2" color="text.secondary">
Impulse is a macOS Virtual/Voice Assistant!{" "}
<i>Impulse is a little buggy and slow.</i>
</Typography>
</CardContent>
<CardActions>
<Button
size="small"
color="primary"
to="/project/impulse"
component={Link}
>
Read More
</Button>
</CardActions>
</Card>
</Grid>
</Grid>
</Grid>
);
}
Some system info:
Google Chrome: 93.0.4577.82 (Official Build) (x86_64)
Revision: e3a25d9b9e2d0b728e045ec87c0aa4942aa46e4e-refs/branch-heads/4577#{#1237}
OS: macOS Version 10.15.7 (Build 19H1417)
JavaScript: V8 9.3.345.19
Thanks!
As you say using material-ui
just add style to your code
material-ui v4.12.3
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles(() => ({
root: {
display: "flex",
justifyContent: "center",
alignItem: "center"
}
}));
and add it to your Grid
export default function App() {
const classes = useStyles();
return (
<Grid container className={classes.root}>
....
)}
check out here
The simpliest answer it's to a div with name of .container and give it width:100% and display:flex;justify-content:center;gap:20px and that's it.
here preview : https://codesandbox.io/s/vigilant-bird-ulpvm?file=/index.html
I'm sending my react-hook-form field to another function component as a children. After pressing Submit Button, the field refreshes and the value inputed is deleted. What is the problem?
CodeSandBox example is here
My file App.js:
import React from "react";
import "./styles.css";
import { useForm } from "react-hook-form";
import { Box, Button, Grid, TextField } from "#material-ui/core";
export default function App() {
const { register, handleSubmit } = useForm();
function onSubmit(data) {
console.log(data);
}
function FieldComponent(props) {
const { title, children } = props;
return (
<Grid container alignItems="center">
<Grid item xs={3}>
<Box py={5}>
<div fontWeight="bold" fontSize="16">
{title}
</div>
</Box>
</Grid>
<Grid item xs={9}>
<Box py={5}>{children}</Box>
</Grid>
</Grid>
);
}
return (
<div className="App">
<Grid container>
<Grid item xs={12}>
<FieldComponent title="name">
<TextField variant="outlined" name="name" inputRef={register} />
</FieldComponent>
</Grid>
<Grid item xs={12}>
<Button variant="outlined" onClick={handleSubmit(onSubmit)}>
Submit
</Button>
</Grid>
</Grid>
</div>
);
}
It's always a good idea to move your sub-component into its own, otherwise, each re-render will mount and unmount your component.
function FieldComponent(props) {
const { title, children } = props;
return (
<Grid container alignItems="center">
<Grid item xs={3}>
<Box py={5}>
<div fontWeight="bold" fontSize="16">
{title}
</div>
</Box>
</Grid>
<Grid item xs={9}>
<Box py={5}>{children}</Box>
</Grid>
</Grid>
);
}
export default function App() {
const { register, handleSubmit } = useForm();
function onSubmit(data) {
console.log(data);
}
return (
<div className="App">
<Grid container>
<Grid item xs={12}>
<FieldComponent title="name">
<TextField variant="outlined" name="name" inputRef={register} />
</FieldComponent>
</Grid>
<Grid item xs={12}>
<Button variant="outlined" onClick={handleSubmit(onSubmit)}>
Submit
</Button>
</Grid>
</Grid>
</div>
);
}
https://codesandbox.io/s/agitated-darkness-leg7z?file=/src/App.js
I try to use material-ui tabs => Fixed Tabs => Full width tabs panel
I have function component OvertiemsReport with Tabs:
const TabContainer = ({children, dir}) => (
<Typography component="div" dir={dir} style={{padding: 8 * 3}}>
{children}
</Typography>
);
const OvertimesReport = ({preview = false, tabValue, handleChange, classes}) => (
<div className={classes.workarea}>
<Card>
<CardContent className="overtimes">
<Typography variant="display2">Отчет о переработках</Typography>
<Grid container spacing={24} className={classes.gridContainer}>
<Grid item>
{preview}
<div className={classes.root}>
<AppBar position="static" color="default">
<Tabs
value={tabValue}
onChange={handleChange}
indicatorColor="primary"
textColor="secondary"
fullWidth
>
<Tab label="Item One"/>
<Tab label="Item Two"/>
</Tabs>
</AppBar>
</div>
</Grid>
</Grid>
</CardContent>
</Card>
</div>
);
and I have external handeChange function
handleChange: value => dispatch(actions.handleChangeTab(value)),
and value stored in redux.
So, after I click to change tab, in input of handeChange I recieve Proxy-object instead just a number of chose tab
Received object in handleChange method like this:
The function given to the onChange prop of the Tabs component is called with the event and value as arguments.
It will work if you change your event handler to this:
handleChange: (event, value) => dispatch(actions.handleChangeTab(value)),