How to add padding between label and control on FormControlLabel - reactjs

I'm trying to have an inline form, where the label is left to the control which doesn't seem to be default usage of various form components.
So far this does the trick:
<Grid container spacing={0}>
<Grid item xs={12}>
<FormControlLabel
label="ID"
disabled
value="42a5936e-9856-42d4-b540-104fd79bcf36"
labelPlacement="start"
control={
<TextField fullWidth name="ID" />
}
/>
</Grid>
</Grid>
But there is no space at all between the label and the control.
Here's what it looks like
I assume some padding-right has to be added to the label, but I'm not sure where I would put that using these components.

Add style to the props of TextField:
<Grid container spacing={0}>
<Grid item xs={12}>
<FormControlLabel
label="ID"
disabled
value="42a5936e-9856-42d4-b540-104fd79bcf36"
labelPlacement="start"
control={
<TextField
fullWidth
name="ID"
style={{ paddingLeft: '20px' }}
/>
}
/>
</Grid>
</Grid>
Alternatively, TextField takes a className prop for you to add classes to the components and style those classes.

To customize the Textfield input zone padding:
Use MUI nesting selector of className MuiInputBase-root
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles(theme => ({
root: {
"& .MuiInputBase-root": {
paddingLeft: 10
}
}
}));
const classes = useStyles();
control={<TextField fullWidth name="ID" className={classes.root} />}
For inline style

Would this work for you?
<TextField
value="42a5936e-9856-42d4-b540-104fd79bcf36"
fullWidth
InputProps={{
startAdornment: (<InputAdornment position="start">ID</InputAdornment>)
}}
/>

Related

Can't access FormData using sign-up form from Material-UI example templates

I'm new to react and fiddling around with Material-UI. I'm trying to use DataPicker and then access the form data with the new FormData() - even though it seems to use TextField, values for start and end are not present. I've used this SignUp form for the beginning.
How do I get them?
App.js
import * as React from 'react';
import Avatar from '#mui/material/Avatar';
import Button from '#mui/material/Button';
import CssBaseline from '#mui/material/CssBaseline';
import TextField from '#mui/material/TextField';
import Link from '#mui/material/Link';
import Grid from '#mui/material/Grid';
import Box from '#mui/material/Box';
import EventAvailableIcon from '#mui/icons-material/EventAvailable';
import Typography from '#mui/material/Typography';
import Container from '#mui/material/Container';
import { createTheme, ThemeProvider } from '#mui/material/styles';
import MyDataPicker from './MyDataPicker';
const theme = createTheme();
export default function SignUp() {
const handleSubmit = (event) => {
event.preventDefault();
const data = new FormData(event.currentTarget);
// eslint-disable-next-line no-console
console.log(data);
// Display the key/value pairs
for (var pair of data.entries()) {
console.log(pair[0] + ': ' + pair[1]);
}
};
return (
<ThemeProvider theme={theme}>
<Container component="main" maxWidth="xs">
<CssBaseline />
<Box
sx={{
marginTop: 8,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
}}
>
<Avatar sx={{ m: 1, bgcolor: 'primary.main' }}>
<EventAvailableIcon />
</Avatar>
<Typography component="h1" variant="h5">
Make Calendar link
</Typography>
<Box component="form" noValidate onSubmit={handleSubmit} sx={{ mt: 3 }}>
<Grid container spacing={2}>
<Grid item xs={12}>
<MyDataPicker
name="start"
label="Start date"
date={null}
/>
</Grid>
<Grid item xs={12}>
<MyDataPicker
name="end"
label="End date"
date={null}
/>
</Grid>
<Grid item xs={12}>
<TextField
required
fullWidth
name="timezone"
label="Timezone"
defaultValue="Europe/Prague"
helperText="See: https://www.php.net/manual/en/timezones.php"
/>
</Grid>
<Grid item xs={12}>
<TextField
required
fullWidth
name="title"
label="Title"
/>
</Grid>
<Grid item xs={12}>
<TextField
multiline
required
fullWidth
name="description"
label="Description"
rows={4}
/>
</Grid>
<Grid item xs={12}>
<TextField
fullWidth
name="location"
label="Location"
/>
</Grid>
</Grid>
<Button
type="submit"
fullWidth
variant="contained"
sx={{ mt: 3, mb: 2 }}
>
Generate links
</Button>
</Box>
</Box>
</Container>
</ThemeProvider>
);
}
MyDataPicker.js
import * as React from 'react';
import Stack from '#mui/material/Stack';
import TextField from '#mui/material/TextField';
import AdapterDateFns from '#mui/lab/AdapterDateFns';
import LocalizationProvider from '#mui/lab/LocalizationProvider';
//https://mui.com/api/date-time-picker/
import DateTimePicker from '#mui/lab/DateTimePicker';
export default function MaterialUIPickers(props) {
const [value, setValue] = React.useState(props.date);
console.log(props);
const handleChange = (newValue) => {
setValue(newValue);
console.log(props);
};
return (
<LocalizationProvider dateAdapter={AdapterDateFns}>
<Stack spacing={3}>
<DateTimePicker
label={props.label}
value={value}
onChange={handleChange}
renderInput={(props) => <TextField {...props} />}
clearable
cleartext="Clear"
/>
</Stack>
</LocalizationProvider>
);
}
You have 2 params with the same name props inside MaterialUIPickers:
export default function MaterialUIPickers(props /* ---------------> props 1 */) {
return (
<LocalizationProvider dateAdapter={AdapterDateFns}>
<Stack spacing={3}>
<DateTimePicker
{...}
renderInput={(props /* ---------------> props 2 */) => {
return (
<TextField {...props} />
);
}}
clearable
cleartext="Clear"
/>
</Stack>
</LocalizationProvider>
);
}
Because props 1 is from the outer scope, it will be overridden by props 2, which prevents you from passing the name attribute down to the input element, that's why the form can't find the field value. The fix is pretty simple, rename one of the props to differentiate between the 2 of them:
renderInput={(params) => {
return (
<TextField
{...params}
{...props} // put props after to let it overrides the name here
inputProps={{
...params.inputProps,
...props.inputProps
}}
InputProps={{
...params.InputProps,
...props.InputProps
}}
/>
);
}}

I wanna to add a little gap on two TextField in Material-UI

Here is my js file, I wanna add a little gap between them like padding. Many people are using box property to declare margin and padding but I don't know why I can't use the box property perfectly. If I use box property like ml={1} then the TextField is upside down. Don't forget the most important part is I wanna use this on a class component, not on a functional component.
<Grid item
xs={12}
sm={6}
md={6}
lg={6}
xl={6}>
<TextField label="Name"
variant="outlined"
color="primary"
size="small"
autoFocus />
<TextField label="Address"
variant="outlined"
color="primary"
size="small"
multiline
rowsMax={1} />
</Grid>
One of the ways to solve is using makeStyles. I have given the complete code. Please review. I have referred to Material UI: Use theme in React Class Component sample for Class Component.
Complete Code using Function Component:
import './App.css';
import React from 'react';
import Grid from '#material-ui/core/Grid';
import { TextField } from '#material-ui/core';
import { makeStyles } from '#material-ui/core/styles';
const useStyles = makeStyles((theme) => ({
control: {
padding: theme.spacing(2),
},
}));
const App = () => {
const classes = useStyles();
return (
<div className="App">
<h1>Hello MERN !!</h1>
<br />
<Grid item xs={12} sm={6} md={6} lg={6} xl={6}>
<TextField label="Name"
className={classes.control}
variant="outlined"
color="primary"
size="small"
autoFocus />
<TextField label="Address"
variant="outlined"
className={classes.control}
color="primary"
size="small"
multiline
rowsMax={1} />
</Grid>
</div >
);
}
export default App;
Complete Code using Class Component:
import React from 'react';
import Grid from '#material-ui/core/Grid';
import { TextField } from '#material-ui/core';
import { withStyles } from "#material-ui/core/styles";
const styles = theme => ({
root: {
padding: theme.spacing(2),
}
});
class Car extends React.Component {
render() {
const { classes } = this.props;
return (
<>
<Grid item xs={12} sm={6} md={6} lg={6} xl={6}>
<TextField label="Name"
variant="outlined"
className={classes.root}
spacing={3}
color="primary"
size="small"
autoFocus />
<TextField label="Address"
variant="outlined"
className={classes.root}
spacing={3}
color="primary"
size="small"
multiline
rowsMax={1} />
</Grid>
</>
);
}
}
export default withStyles(styles, { withTheme: true })(Car);
Make sure your Grid item property in a Grid container.You have to wrap the Grid item property in a Grid Container Property.

Create MUI TextField Next to Label

I've searched all over, but I can't make it work. I want to create a TextField Element Next to a label
(and not anywhere inside or touching the border of a TextField) like this one:
Desired Result
Labe <____> TextField
Such a scenario is not covered in the documentation.
The best i could get was to use the startAdornment in the TextField Component.
InputProps={{
startAdornment: (
<InputAdornment position="start">Name</InputAdornment>
)
}}
Also I tried, to use the FormControlLabel component and pass inside the TextField as a Control, although TextField can't be anymore fullWidth
<FormControlLabel
control={<TextField
variant="standard"
margin="normal"
id="tags"
helperText="service."
fullWidth
/>}
label="Start"
labelPlacement="start"
/>
But it doesn't seem to work properly and I'm not even sure if I should use a FormControlLabel with a TextField.
Thank you in advance. This seems as something very basic but I can't get it to work and I find no other relative problems posted.
you can apply a flex style to your Form or wrap your Textfield in a div with an InputLabelin it like and add style to match the desire result for example like this:
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import TextField from "#material-ui/core/TextField";
import InputLabel from "#material-ui/core/InputLabel";
import { FormHelperText } from "#material-ui/core";
const useStyles = makeStyles((theme) => ({
root: {
display: "flex"
},
TextFieldDiv: {
marginLeft: "15px"
},
labelName: {
paddingTop: "10px"
},
optionalTag: {
fontSize: "13px"
},
labelTag: {
textAlign: "right"
}
}));
export default function BasicTextFields() {
const classes = useStyles();
return (
<form className={classes.root} noValidate autoComplete="off">
<InputLabel className={classes.labelName}>
<div className={classes.labelTag}>Name</div>{" "}
<div className={classes.optionalTag}>(optional)</div>
</InputLabel>
<div className={classes.TextFieldDiv}>
<TextField id="standard-basic" />
<FormHelperText>The service name</FormHelperText>
</div>
</form>
);
}
here a sandBox Example
I tried the above solutions and these are not working in Mui-v5.
You can use Grid.
<Grid container direction="row" alignItems="center" spacing={2}>
<Grid item>
<div>Label</div>
</Grid>
<Grid item>
<div>Input</div>
</Grid>
</Grid>
You can adjust spacing and alignment accordingly.

Material UI OutlinedInput label is invisible

We are using OutlinedInput from Material UI, but text labels are not rendered. How to fix this?
import { Grid, OutlinedInput } from '#material-ui/core';
<Grid container>
<Grid item xs={12}>
<OutlinedInput
label="invisible label"
placeholder="HELLO, STACKOVERFLOW!"
value={value}
onChange={(e) => handleValueChange(e.target.value)}
fullWidth
/>
</Grid>
</Grid>
instead of expected "invisible label" text, an empty space is rendered (top left corner):
Like #Daniel L mentioned, you have to use the InputLabel component within the FormControl component, but in addition to his answer - I had to add a label attribute on my OutlinedInput component so that the outline on the input would not overlap with my label.
Code without the label attribute:
<FormControl sx={{ m: 1, width: '25ch' }} variant="outlined">
<InputLabel htmlFor='display-name'>Display Name</InputLabel>
<OutlinedInput
id="display-name"
value={displayName}
onChange={(e) => handleInputChange(e)}
aria-describedby="base-name-helper-text"
inputProps={{
'aria-label': 'weight',
}}
/>
</FormControl>
Code WITH the label attribute:
<FormControl sx={{ m: 1, width: '25ch' }} variant="outlined">
<InputLabel htmlFor='display-name'>Display Name</InputLabel>
<OutlinedInput
id="display-name"
value={displayName}
label='Display Name'
onChange={(e) => handleInputChange(e)}
aria-describedby="base-name-helper-text"
inputProps={{
'aria-label': 'weight',
}}
/>
</FormControl>
I don't think this component is meant to be used on its own. In the MUI docs, it is primarily used as augmentation for other components such as TextField
<TextField id="outlined-basic" label="Outlined" variant="outlined" />
If you inspect the styles in dev tools, it looks like the CSS property visibility: hidden is causing this issue. In fact, if you remove that style, you will see that the label works.
However, if you have already built the majority of your app with this component and you need to show that label, just override it with MUI's styling solutions such as makeStyles. In addition, use notched prop to allocate space for it
const useStyles = makeStyles({
customInputLabel: {
"& legend": {
visibility: "visible"
}
}
});
export default function App() {
const classes = useStyles();
return (
<div className="App">
<Grid container>
<Grid item xs={12}>
<OutlinedInput
classes={{ notchedOutline: classes.customInputLabel }}
label="visible label"
placeholder="HELLO, STACKOVERFLOW!"
fullWidth
notched
/>
</Grid>
</Grid>
</div>
);
}
I had the same issue and I wrapped OutlinedInput into the FormControl element and attached InputLabe component as a label and that fixed my issue.
The quick answer to this is basically wrapping the component under a FormControl and adding an InputLabel on top of the OutlinedInput component.
Based on your code, it should look like this:
<Grid container>
<Grid item xs={12}>
<FormControl>
<InputLabel htmlFor="outlined-adornment">Some text</InputLabel>
<OutlinedInput
id="outlined-adornment"
placeholder="HELLO, STACKOVERFLOW!"
value={value}
onChange={(e) => handleValueChange(e.target.value)}
fullWidth
/>
</FormControl>
</Grid>
</Grid>

How to make TextField input wider?

I have the following code:
<Grid
container
spacing={0}
direction="column"
alignItems="center"
justify="center"
style={{ minHeight: "100vh" }}
>
<FormControl>
<TextField
label="email"
fullWidth
type="email"
value={email}
onChange={e => setEmail(e.target.value)}
></TextField>
<TextField
label="body"
type="body"
fullWidth
value={body}
onChange={e => setBody(e.target.value)}
multiline={true}
></TextField>
</FormControl>
</Grid>
And this renders:
The reason I'm using Grid is because I wanted to center the form, as suggested from the answers here.
No matter what I do, I can't get the TextField to change width. I've added it into a Container, I've added the width style, nothing works. What am I doing wrong here?
According to Material-UI TextField docs, fullWidth prop:
If true, the input will take up the full width of its container.
The TextField container in this case is FormControl, and the FormControl width is calculated to contain it's children.
If you set FormControl to fullWidth as well, you will get what you want:
<FormControl fullWidth>

Resources