I am using this form with material-ui components. Instead of writing the inline style that I am currently using for width, I wanted to opt for css-in-js. I have used styled-components previously but I don't think there's a form element with that.
The only example I came across was one where they had used built-in styled component labels. Since I have implemented validation on these material ui text fields as well so I don't want to change the structure. What would be the suitable way to put the style in css-in-js. I would prefer if there's a solution with styled-components.
return (
<div className="main-content">
<form
style={{ width: '100%' }}
onSubmit={e => {
e.preventDefault();
submitForm(email);
}}>
<div>
<TextField
variant="outlined"
margin="normal"
id="email"
name="email"
helperText={touched.email ? errors.email : ''}
error={touched.email && Boolean(errors.email)}
label="Email"
value={email}
onChange={change.bind(null, 'email')}
/>
<CustomButton
disabled={!isValid || !email}
text={'Remove User'}
/>
</div>
</form>
</div>
);
just make the styled form:
import styled from 'styled-components';
const Form = styled.form`
width: 100%;
`;
and use it:
return (
<div className="main-content">
<Form
onSubmit={e => {
e.preventDefault();
submitForm(email);
}}>
<div>
<TextField
variant="outlined"
margin="normal"
id="email"
name="email"
helperText={touched.email ? errors.email : ''}
error={touched.email && Boolean(errors.email)}
label="Email"
value={email}
onChange={change.bind(null, 'email')}
/>
<CustomButton
disabled={!isValid || !email}
text={'Remove User'}
/>
</div>
</Form>
</div>
);
Related
const updateCreateFormField = (e) => {
const { name, value } = e.target;
setCreatForm({
...createForm,
[name]: value,
})
console.log({ name, value });
};
//The onChange variable in the fields is updated on the above code. I am unable to find the solution towards making the below fields function properly. I tried using formik's setFieldValue however It didn't work
const formik = useFormik({
initialValues: {
Name: "",
Address: "",
phoneNumber: "",
Email: "",
}
})
The below code is the return function:
return (<div className="App">
{updateForm._id && (<div>
<h2>Update Customer:</h2>
<Box height={20} />
<Formik initialValues={formik.initialValues}
validationSchema={object({
Name: string().required("Please enter a name").min(3, "Name is too short"),
Address: string().required("Please enter an address").min(3, "Address is too short"),
phoneNumber: number().required("Please enter a phone number").min(4, "Phone number is too short"),
Email: string().required("Please enter an email").email("Invalid email"),
})}
onSubmit={(values, formikHelpers) => {
console.log(values);
formikHelpers.resetForm();
}}
>
{({ errors, isValid, touched, dirty }) => (
<Form onSubmit={updateCustomer}>
<Field name="Name" type="name" as={TextField} variant="outlined" color="primary" label="Name" fullWidth
onChange={handleUpdateFieldChange}
value={updateForm.Name}
error={Boolean(errors.Name) && Boolean(touched.Name)}
helperText={Boolean(touched.Name) && errors.Name}
/>
<Box height={14} />
<Field name="Address" type="Address" as={TextField} variant="outlined" color="primary" label="Address" fullWidth
onChange={handleUpdateFieldChange}
value={updateForm.Address}
error={Boolean(errors.Address) && Boolean(touched.Address)}
helperText={Boolean(touched.Address) && errors.Address}
/>
<Box height={14} />
<Field name="phoneNumber" type="number" as={TextField} variant="outlined" color="primary" label="Phone Number" fullWidth
error={Boolean(errors.phoneNumber) && Boolean(touched.phoneNumber)}
helperText={Boolean(touched.phoneNumber) && errors.phoneNumber}
onChange={handleUpdateFieldChange}
value={updateForm.phoneNumber}
/>
<Box height={14} />
<Field name="Email" type="email" as={TextField} variant="outlined" color="primary" label="Email" fullWidth
error={Boolean(errors.Email) && Boolean(touched.Email)}
helperText={Boolean(touched.Email) && errors.Email}
onChange={handleUpdateFieldChange}
value={updateForm.Email}
/>
<Box height={16} />
<Button type="submit" variant="contained" color="primary" size="large" disabled={!dirty || !isValid} >Update Customer</Button>
</Form>
)}
</Formik>
</div>)}
{!updateForm._id && <div>
<h2>Create Customer:</h2>
<Box height={20} />
<Formik initialValues={formik.initialValues}
validationSchema={object({
Name: string().required("Please enter a name").min(3, "Name is too short"),
Address: string().required("Please enter an address").min(3, "Address is too short"),
phoneNumber: number().required("Please enter a phone number").min(4, "Phone number is too short"),
Email: string().required("Please enter an email").email("Invalid email"),
})}
onSubmit={(values, formikHelpers) => {
console.log(values);
formikHelpers.resetForm();
}}
>
{({ setFieldValue, errors, isValid, touched, dirty,handleBlur,handleSubmit}) => (
<Form onSubmit={createCustomer} >
<Field as={TextField} name="Name" type="name" variant="outlined" color="primary" label="Name" fullWidth
onChange={updateCreateFormField} value={createForm.Name}
error={Boolean(errors.Name) && Boolean(touched.Name)}
helperText={Boolean(touched.Name) && errors.Name}
/>
<Box height={14} />
<Field name="Address" type="Address" as={TextField} variant="outlined" color="primary" label="Address" fullWidth
error={Boolean(errors.Address) && Boolean(touched.Address)}
helperText={Boolean(touched.Address) && errors.Address}
onChange={updateCreateFormField} value={createForm.Address}
/>
<Box height={14} />
<Field name="phoneNumber" type="number" as={TextField} variant="outlined" color="primary" label="Phone Number" fullWidth
error={Boolean(errors.phoneNumber) && Boolean(touched.phoneNumber)}
helperText={Boolean(touched.phoneNumber) && errors.phoneNumber}
onChange={updateCreateFormField}
value={createForm.phoneNumber}
/>
<Box height={14} />
<Field name="Email" type="email" as={TextField} variant="outlined" color="primary" label="Email" fullWidth
error={Boolean(errors.Email) && Boolean(touched.Email)}
helperText={Boolean(touched.Email) && errors.Email}
onChange={updateCreateFormField}
value={createForm.Email}
/>
<Box height={16} />
<Button type="submit" variant="contained" color="primary" size="large" disabled={!dirty || !isValid} >Create Customer</Button>
</Form>
)}
</Formik>
</div>}
<Box height={40} />
</div>
)
Sandbox
Simply use Formik's handleChange event and values. You don't need to create custom functions or states to change values.
Working example here
Also, if you want to have custom function to have inside onChange you can use formik's setFieldValue.
More information related to formik events https://formik.org/docs/api/formik
I have a form that has a few textfields in it. If you have a certain role then you should be able to click in the fields and type but if you do not have the admin role then they should all be disabled. How would I disable all the textfields given this situation? Here is my code. I am fairly new to react and any help would be appreciated.
I could do something like this but is there an easier way with less repetition as this form is most definitely to get bigger and more complex and I should be able to disable the entire thing if not given the correct role.
export default function BasicTextFields() {
const classes = useStyles();
const hasRole = authService.verifyRole(role.admin)
return (
{hasRole ? (
<form className={classes.root} noValidate autoComplete="off">
<TextField id="standard-basic" label="Title" />
<TextField id="filled-basic" label="Description" />
<TextField id="outlined-basic" label="Data" variant="outlined" />
</form>
);
) : (
<form className={classes.root} noValidate autoComplete="off">
<TextField id="standard-basic" label="Title" disabled/>
<TextField id="filled-basic" label="Description" disabled/>
<TextField id="outlined-basic" label="Data" variant="outlined" disabled/>
</form>
}
Rather than duplicating your elements and passing disabled as a single keyword (which is a shorthand for disabled={true}, you can explicitly pass a boolean value to it:
export default function BasicTextFields() {
const classes = useStyles();
const hasRole = authService.verifyRole(role.admin)
return (
<form className={classes.root} noValidate autoComplete="off">
<TextField id="standard-basic" label="Title" disabled={!hasRole}/>
<TextField id="filled-basic" label="Description" disabled={!hasRole}/>
<TextField id="outlined-basic" label="Data" variant="outlined" disabled={!hasRole}/>
</form>
);
}
Little simpler...
<form className={classes.root} noValidate autoComplete="off">
<TextField id="standard-basic" label="Title" disabled={!hasRole}/>
<TextField id="filled-basic" label="Description" disabled={!hasRole} />
<TextField id="outlined-basic" label="Data" variant="outlined" disabled={!hasRole}/>
</form>
I have created an API login/register system with Django and React.js, I have my Back-End up and running, the registration system itself is fully functioning, what I need right now is a way to display response messages after the API call from React.js to Django. All the errors after API call are being stored as object in the state. So far I just displayed all the messages like this:
What I need now is a way to make them look like this:
So basically the error message itself JSX code is:
<small style={{color: '#ea0027',marginBottom: '0.5rem',fontWeight: 'bold',}}>
<li style={{ listStyleType: 'circle' }}>{name} {error}</li>
</small>
And this is how I render the messages now:
{Object.entries(this.state.errors).map(([name, error]) => (
<small style={{color: '#ea0027',marginBottom: '0.5rem',fontWeight: 'bold'}}>
<li style={{ listStyleType: 'circle' }}>{name} {error}</li>
</small>
))}
maybe somthing like this. i dont know how the data in this.state.error looks so maybe you can select it out of error like in this example
{Object.entries(this.state.errors).map(([name, error]) => (
return (
<>
<li style={{ listStyleType: "circle" }}>
<RegisterInput
type="text"
invalid={true}
name="username"
value={this.state.username}
placeholder="Choose a username"
autoComplete="new-username"
onChange={(e) => this.onChange(e)}
pattern="^(?=[a-zA-Z0-9._]{3,20}$)(?!.*[_.]{2})[^_.].*[^_.]$"
/>
{error.username}
</li>
<li style={{ listStyleType: "circle" }}>
<RegisterInput
type="email"
name="email"
value={this.state.email}
autoComplete="new-email"
placeholder="Enter your email address"
onChange={(e) => this.onChange(e)}
/>
{error.email}
</li>
<li style={{ listStyleType: "circle" }}>
<RegisterInput
type="password"
name="password"
value={this.state.password}
placeholder="Password"
autoComplete="new-password"
onChange={(e) => this.onChange(e)}
/>
{error.password}
</li>
<li style={{ listStyleType: "circle" }}>
<RegisterInput
type="password"
name="re_password"
value={this.state.re_password}
placeholder="Confirm password"
autoComplete="new-re-password"
onChange={(e) => this.onChange(e)}
/>
{error.re_password}
</li>
</>
)
))}
I want to make a textField clickable so that a dialog box opens for the user to type in more text.
Do you have any idea how can I make that happen with the help of MaterialUI?
This is my current solution, where a button is displayed to open the dialogbox (instead of making the textField itself clickable):
<form noValidate autoComplete="off">
<TextFieldDialog />
<TextField
id="outlined-multiline-static"
label="Frage"
multiline
rows={4}
placeholder="Tippe hier die Frage ein!"
onChange={this.handleChange.bind(this)}
variant="outlined"
style={{
backgroundColor: "white",
}}
>
</form>
You could implement onClick on TextField
const [dialogOpen, setDialogOpen] = useState(false)
return (
<div>
<TextField
id="outlined-basic"
label="Outlined"
variant="outlined"
onClick={() => setDialogOpen(true)}
/>
<Dialog open={dialogOpen} onClose={() => setDialogOpen(false)}>
<DialogTitle>Sample Dialog</DialogTitle>
<DialogContent dividers>
<Typography>Your content here</Typography>
</DialogContent>
</Dialog>
</div>
)
Codesandbox demo
In Formik, I try to use {...formik.getFieldProps('email')} on my input field
instead of using value, onChange, and onBlur. But it's not working.
This works :
<input id="email" name="email" type="text" value={formik.values.email} onChange={formik.handleChange} onBlur={formik.handleBlur} />
But this doesn't :
<input id="email" type="text" {...formik.getFieldProps("email")} />
Code is here : https://codesandbox.io/s/formik-pb-with-getfieldprops-83tze?fontsize=14
Any ideas ?
Thanks !
As MiDas said, what you are doing should work if you are on latest version.
I'll mention an even more concise alternative: the Field component.
Field component handles the field property propagation for you.
Simple example:
<Field name="email" type="text" />
Notice that you don't need to do {...formik.getFieldProps("email")}, or any other "boilerplate".
Related to Field is useField, which can be used to make custom form components just as easy to use - no "boilerplate" needed.
A custom component:
function TextInputWithLabel({ label, ...props }) {
// useField() returns [formik.getFieldProps(), formik.getFieldMeta()]
// which we can spread on <input> and also replace ErrorMessage entirely.
const [field, meta] = useField(props);
return (
<>
<label
htmlFor={props.id || props.name}
css={{ backgroundColor: props.backgroundColor }}
>
{label}
</label>
<input className="text-input" {...field} type="text" {...props} />
{meta.touched && meta.error ? (
<div className="error">{meta.error}</div>
) : null}
</>
);
}
Usage:
<TextInputWithLabel name="input1" label="Random comment" />
As seen in code from codesandbox.