I have an authorization and validation form for registration. I need to to make my form available for click events at my button. At first i added the resetform function in order to notice how my form actually works but after each click nothing happens.
import { Button, TextField } from "#mui/material";
import * as yup from "yup";
import { Formik } from "formik";
export const RegistrationForm = () => {
const validationSchema = yup.object().shape({
name: yup
.string()
.typeError("Должно быть строкой")
.required("Обязательно")
.matches(/^[аА-яЯ\s]+$/, "Имя должно состоять из русских букв"),
secondName: yup
.string()
.typeError("Должно быть строкой")
.required("Обязательно")
.matches(/^[аА-яЯ\s]+$/, "Фамилия должна состоять из русских букв"),
login: yup
.string()
.typeError("Должно быть строкой")
.required("Обязательно"),
password: yup
.string()
.typeError("Должно быть строкой")
.required("Обязательно"),
confirmPassword: yup
.string()
.oneOf([yup.ref("password")], "Пароли не совпадают")
.required("Обязательно"),
email: yup.string().email("Введите верный email").required("Обязательно"),
confirmEmail: yup
.string()
.email("Введите верный email")
.oneOf([yup.ref("email")], "Email не совпадают")
.required("Обязательно"),
});
return (
<>
<header>
<div className="head-btns">
<Button variant="outlined">Зарегистрироваться</Button>
<Button variant="outlined">Авторизоваться</Button>
</div>
</header>
<Formik
initialValues={{
name: "",
secondName: "",
login: "",
password: "",
confirmPassword: "",
email: "",
confirmEmail: "",
}}
validateOnBlur
onSubmit={({ resetForm }) => resetForm()}
validationSchema={validationSchema}
>
{({
values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit,
isValid,
dirty,
}) => (
<div className="register">
<TextField
id="outlined-basic"
label="Имя"
variant="outlined"
className="field"
name={"name"}
onChange={handleChange}
onBlur={handleBlur}
value={values.name}
/>
{touched.name && errors.name && (
<p className={"error"}>{errors.name}</p>
)}
<TextField
id="outlined-basic"
label="Фамилия"
variant="outlined"
className="field"
name={"secondName"}
onChange={handleChange}
onBlur={handleBlur}
value={values.secondName}
/>
{touched.secondName && errors.secondName && (
<p className={"error"}>{errors.secondName}</p>
)}
<TextField
id="outlined-basic"
label="Логин"
variant="outlined"
className="field"
name={"login"}
onChange={handleChange}
onBlur={handleBlur}
value={values.login}
/>
{touched.login && errors.login && (
<p className={"error"}>{errors.login}</p>
)}
<TextField
type="password"
id="outlined-basic"
label="Пароль"
variant="outlined"
className="field"
name={"password"}
onChange={handleChange}
onBlur={handleBlur}
value={values.password}
/>
{touched.password && errors.password && (
<p className={"error"}>{errors.password}</p>
)}
<TextField
type="password"
id="outlined-basic"
label="Подтвердите пароль"
variant="outlined"
className="field"
name={"confirmPassword"}
onChange={handleChange}
onBlur={handleBlur}
value={values.confirmPassword}
/>
{touched.confirmPassword && errors.confirmPassword && (
<p className={"error"}>{errors.confirmPassword}</p>
)}
<TextField
id="outlined-basic"
label="Email"
variant="outlined"
className="field"
name={"email"}
onChange={handleChange}
onBlur={handleBlur}
value={values.email}
/>
{touched.email && errors.email && (
<p className={"error"}>{errors.email}</p>
)}
<TextField
id="outlined-basic"
label="Подтвердите Email"
variant="outlined"
className="field"
name={"confirmEmail"}
onChange={handleChange}
onBlur={handleBlur}
value={values.confirmEmail}
/>
{touched.confirmEmail && errors.confirmEmail && (
<p className={"error"}>{errors.confirmEmail}</p>
)}
<Button
onClick={handleSubmit}
disabled={!isValid || !dirty}
type="submit"
variant="contained"
className="btn"
>
Зарегистрироваться
</Button>
</div>
)}
</Formik>
</>
);
};
I clicked the button and nothing happens but it should reset all inputs after this action
The onSubmit prop given to the <Formik /> component should be like this:
<Formik
onSubmit={(values, { resetForm }) => resetForm()}
validationSchema={validationSchema}
>
</Formik>
Formik options are passed to the second parameter of the submit handler.
And you don't need to explicitly give your Button onClick handler with type="submit" if you define your form in the HTML form tag.
<Formik
onSubmit={(values, { resetForm }) => resetForm()}
validationSchema={validationSchema}
>
{({ handleSubmit }) => (
<form onSubmit={handleSubmit>
{/* your form */}
<Button
type="submit" // giving type submit to a button enclosed in a form will automatically call handleSubmit method
>
Submit
</Button>
</form>
)}
</Formik>
Related
So, I've made a registration form in the React App, using Bootstrap for the style, Formik and Yup for the validation. I want to change a Submit Button class to 'btn-outline-danger' and make it disabled till the form inputs are valid. I know it doesn't affect the real functionality, but anyways I'd like to manipulate with the button's style.
import React from 'react';
import { Button, Form as FormStrap } from 'react-bootstrap';
import { Link } from 'react-router-dom';
import * as yup from 'yup';
import { Formik, Form, Field } from 'formik';
const REGISTRATION_SCHEMA = yup.object().shape({
name: yup
.string()
.min(2, 'Too Short!')
.max(24, 'Too Long!')
.required('Required'),
email: yup.string().email('Invalid email').required('Required'),
password: yup
.string()
.min(6, 'Too Short!')
.max(14, 'Too Long!')
.required('Required'),
passwordConfirmation: yup
.string()
.oneOf([yup.ref('password'), null], 'Passwords do not match'),
});
export default function RegistrationForm() {
return (
<>
<Formik
validationSchema={REGISTRATION_SCHEMA}
initialValues={{
name: '',
email: '',
password: '',
passwordConfirmation: '',
}}
onSubmit={(values) => {
// same shape as initial values
console.log(values);
}}
// validate={validate}
>
{({ handleSubmit, handleChange, values, touched, errors }) => (
<Form id='registration-form' onSubmit={handleSubmit}>
<FormStrap.Group className='mb-3' controlId='registration-name'>
<FormStrap.Label>Name</FormStrap.Label>
<Field
className='form-control'
type='text'
placeholder='Enter name'
name='name'
value={values.name}
onChange={handleChange}
/>
{errors.name && touched.name ? (
<FormStrap.Text>{errors.name}</FormStrap.Text>
) : null}
</FormStrap.Group>
<FormStrap.Group className='mb-3' controlId='registration-email'>
<FormStrap.Label>Email </FormStrap.Label>
<Field
className='form-control'
type='email'
placeholder='Enter email'
name='email'
value={values.email}
onChange={handleChange}
/>
{errors.email && touched.email ? (
<FormStrap.Text>{errors.email}</FormStrap.Text>
) : null}
</FormStrap.Group>
<FormStrap.Group className='mb-3' controlId='registration-password'>
<FormStrap.Label>Password</FormStrap.Label>
<Field
className='form-control'
type='password'
placeholder='Enter password'
name='password'
value={values.password}
onChange={handleChange}
/>
{errors.password && touched.password ? (
<FormStrap.Text>{errors.password}</FormStrap.Text>
) : null}
<Field
className='mt-2 form-control'
type='password'
placeholder='Confirm password'
name='passwordConfirmation'
value={values.passwordConfirmation}
onChange={handleChange}
/>
{errors.passwordConfirmation && touched.passwordConfirmation ? (
<FormStrap.Text>{errors.passwordConfirmation}</FormStrap.Text>
) : null}
</FormStrap.Group>
<FormStrap.Group className='mb-3' controlId='registration-submit'>
<Button variant='success' type='submit' disabled={!errors}>
Sign Up
</Button>
</FormStrap.Group>
<FormStrap.Group className='mb-3'>
<FormStrap.Text className='text-muted'>
Already have an account? <Link to='/login'>Sign in now</Link>
</FormStrap.Text>
</FormStrap.Group>
</Form>
)}
</Formik>
</>
);
}
I will rewrite just the button part
<FormStrap.Group className='mb-3' controlId='registration-submit'>
<Button
variant='success'
type='submit'
disabled={Object.keys(errors).length > 0}
className={`${Object.keys(errors).length > 0 ? 'btn-outline-danger': ''}`}>
Sign Up
</Button>
</FormStrap.Group>
I am trying to make a simple login form i want to render an element when an input field is clicked . I have done this in normal react form by rendering an element by changing the value of a boolean variable to true and when the input is written if the user touch somewhere else then the element disapears . kind of toggle thing . but i don't know hoe to do this in formik. my code looks like this.
import React from "react";
import { Formik } from "formik";
import * as EmailValidator from "email-validator";
import * as Yup from "yup";
const ValidatedLoginForm = () => (
<Formik
initialValues={{ email: "", password: "" }}
onSubmit={(values, { setSubmitting }) => {
console.log(values);
console.log("hello there ");
}}
validationSchema={Yup.object().shape({
email: Yup.string()
.email()
.required("Required"),
password: Yup.string()
.required("No password provided.")
.min(8, "Password is too short - should be 8 chars minimum.")
.matches(/(?=.*[0-9])/, "Password must contain a number.")
})}>
{props => {
const {
values,
touched,
errors,
isSubmitting,
handleChange,
handleBlur,
handleSubmit
} = props;
return (
<div className="container">
<div className="row">
<form onSubmit={handleSubmit}>
<br />
<input
name="email"
type="text"
placeholder="Enter your email"
value={values.email}
onChange={handleChange}
onBlur={handleBlur}
className={errors.email && touched.email && "error"}
/>
<br />
<br />
{errors.email && touched.email && (
<div className="input-feedback">{errors.email}</div>
)}
<br />
<input
name="password"
type="password"
placeholder="Enter your password"
value={values.password}
onChange={handleChange}
onBlur={handleBlur}
className={errors.password && touched.password && "error"}
/> <br />
<br />
{errors.password && touched.password && (
<div className="input-feedback">{errors.password}</div>
)}
<button type="submit" disabled={isSubmitting}>
Login
</button>
</form>
</div>
<div className="row">
<button className="btn btn-default">Value</button>
</div>
</div>
);
}}
Maybe this will help you. Try to add function to onBlur prop then handle handleBlur function.
onBlur={(e) => {
handleBlur(e);
// here handle component showing
}}
I have a form in my react component with handleSubmit. What I need to do is when I submit the form(on save click) the save button automatically should get disabled and when I get the response it automatically gets enabled.
handleSubmit = async({ company, email }, { setSubmitting, setErrors }) => {
setSubmitting(true)
const { value: { status, message } } = await this.props.createCompany({ name: company, email })
if (status) {
this.fetchCompanies()
this.closeModal()
} else {
setErrors({ email: message })
}
}
<Formik
initialValues={loginDetails}
validationSchema={loginSchema}
onSubmit={(values, formikProps) => this.handleSubmit(values, formikProps)}
>
{({
values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit,
isSubmitting
}) => (
<form onSubmit={handleSubmit}>
<div className="col-md-12">
<div className="form-group material-textfield">
<input type="text" name="email" value={values.email} onChange={handleChange} className="form-control material-textfield-input"/>
<ErrorMessage component="span" name="email" className="invalid-feedback d-block"/>
<label className="material-textfield-label">Email<span>*</span></label>
</div>
</div>
<button type="submit" className="btn btn-dark btn-lg w-100" disabled={isSubmitting}>Save</button>
</form>
)}
</Formik>
And for this I have used setSubmitting function from formik. But it doesn't work.
Kindly help.
This should help:
const onSubmitHandler = (values, formik) => {
persistYourData(values).then(r => {
formik.setSubmitting(false);
}).catch(error => console.log(error));
}
...
<Button variant="contained" color={"primary"} onClick={pr.handleSubmit} disabled={ ((!(pr.isValid && pr.dirty)) || pr.isSubmitting) }>Submit</Button>
#You can disable the button with **formik.isSubmitting** or **formik.errors** #
<Formik
initialValues={{
email: '',
password: '',
}}
validationSchema={Yup.object({
email: Yup.string().email('Invalid email address').required('Required'),
password: Yup.string().required('Required'),
})}
onSubmit={(values, { setSubmitting }) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
setSubmitting(false);
});
}}
>
{(formik) => (
<Form>
<h1>Login</h1>
<Field type='email' name='email' />
<br />
<ErrorMessage name='email' />
<br />
<Field type='password' name='password' />
<br />
<ErrorMessage name='password' />
<br />
<button disabled={formik.isSubmitting || formik.errors}>Login</button>
</Form>
)}
</Formik>
I have a form that i'm controlling by formik, when i fill all the fields and press the buttom submit, the function onSubmit is called and my form have this values reseted.
Sometimes my data is incorrect (like a duplicate email) and i need to persist this data.
How i can do this?
This is my code:
const schema = Yup.object().shape({
login: Yup.string()
.email('Email não possui formato válido')
.required('Informe o email!'),
password: Yup.string().required('Informe a senha!'),
})
const formik = useFormik({
initialValues: {
login: '', password: '', inactive: false
},
validationSchema: schema,
onSubmit: values => {
registerUser(values)
}
})
return (
<form onSubmit={formik.handleSubmit} className={classes.form} noValidate>
<Grid container spacing={3}>
<Grid item xs={12}>
<Typography className={classes.observation} component="h6">* Necessário preenchimento do cadastro geral para liberar permissão de telas</Typography>
</Grid>
<Grid item xs={5}>
<TextField
value={formik.values.login}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={formik.touched.login ? formik.errors.login : ""}
error={formik.touched.login && Boolean(formik.errors.login)}
variant="outlined"
margin="normal"
required
fullWidth
id="email"
label="E-mail"
name="login"
autoComplete="email"
/>
</Grid>
<Grid item xs={5}>
<TextField
value={formik.values.password}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
helperText={formik.touched.password ? formik.errors.password : ""}
error={formik.touched.password && Boolean(formik.errors.password)}
variant="outlined"
margin="normal"
required
fullWidth
type="password"
id="password"
label="Senha"
name="password"
/>
</Grid>
<Grid item xs={2}>
<FormControlLabel
onChange={formik.handleChange}
onBlur={formik.handleBlur}
value={formik.values.inactive}
control={<Switch color="primary" />}
label="Inativo"
labelPlacement="top"
/>
</Grid>
<Grid item xs={3}>
<Button fullWidth
variant="contained"
color="primary"
type="submit"
>
Cadastrar
</Button>
</Grid>
</Grid>
</form>
);
Use the Form from formik, and the default is to not reset on submit:
import { Formik, Form } from "formik";
function DemoComp(){
return(
<Formik
initialValues={{ fieldOneVal: "" }}
onSubmit={async (formsData, {setSubmitting, resetForm}) => {
setSubmitting(true)
// async request
// --> if wanted to reset on submit: resetForm();
console.log(formsData)
setSubmitting(false)
}}
>
{({ values, isSubmitting, handleChange, handleBlur, handleSubmit }) => (
<Form>
<input
type="text"
name="fieldOneVal"
value={values.fieldOneVal}
onChange={handleChange}
onBlur={handleBlur}
/>
<button type="submit">Submit</button>
</Form>
)}
</Formik>
)
}
You need to update the following line:
<form onSubmit={(e) => { e.preventDefault(); formik.handleSubmit(e)}} className={classes.form} noValidate>
You need to define the function to be async and as async response handling is not mention in your code so it's hard to give exact solution
<Formik
initialValues={{ fieldOneVal: formvalues.fieldOneVal }}
onSubmit={async (values, { resetForm }) => {
// setFormvalues(({fieldOneVal:values.fieldOneval}) don't know why you're manipulating state
const resp=await someAsyncFunc()
if (resp){
reset the state to initial values}
else{
pop up modal display with errors}
}}
>
I faced the same problem formik resetting the form before i get a response from the server.This solution helped me.
import { Formik, Form } from "formik";
function DemoComp(){
const [formvalues,setFormvalues]= useState({
{ fieldOneVal: "" }
)
return(
<Formik
initialValues={{ fieldOneVal: formvalues.fieldOneVal }}
onSubmit={(values, { resetForm }) => {
setFormvalues(({fieldOneVal:values.fieldOneval})
// async request
if sucess{
reset the state to initial values}
else{
pop up modal display with errors}
}}
>
{({ values, isSubmitting, handleChange, handleBlur, handleSubmit }) => (
<Form>
<input
type="text"
name="fieldOneVal"
value={values.fieldOneVal}
onChange={handleChange}
onBlur={handleBlur}
/>
<button type="submit">Submit</button>
</Form>
)}
</Formik>
)
}
I'm new to react, and I'm trying to apply validations to a form.
For some reason when adding the property:
onChange={onChange}
I want to send the values to the parent component. That's why I'm using the onchange.
Nothing I write is shown in my text fields, why does this happen?
export const Son = props => {
const { onChange } = props;
return (
<Formik
initialValues={{
fullname: "",
email: ""
}}
validationSchema={Yup.object().shape({
fullname: Yup.string()
.min(2, "Your name is too short")
.required("Please enter your full name"),
email: Yup.string()
.email("The email is incorrect")
.required("Please enter your email")
})}
onSubmit={(values, { setSubmitting }) => {
const timeOut = setTimeout(() => {
console.log(values);
setSubmitting(false);
clearTimeout(timeOut);
}, 1000);
}}
>
{({
values,
errors,
touched,
handleSubmit,
isSubmitting,
validating,
valid
}) => {
return (
<Form name="contact" method="post" onSubmit={handleSubmit}>
<label htmlFor="fullname">
Fullname
<Field
type="text"
name="fullname"
autoComplete="name"
placeholder="your fullname"
onChange={onChange}
/>
</label>
{<ErrorMessage name="fullname">{msg => <p>{msg}</p>}</ErrorMessage>}
{/*errors.fullname && touched.fullname && <p>{errors.fullname}</p>*/}
<br />
<label htmlFor="email">
Email
<Field
type="email"
name="email"
autoComplete="email"
placeholder="your email"
onChange={onChange}
/>
</label>
<ErrorMessage name="email">{msg => <p>{msg}</p>}</ErrorMessage>
<br />
<button type="submit" disabled={!valid || isSubmitting}>
{isSubmitting ? `Submiting...` : `Submit`}
</button>
</Form>
);
}}
</Formik>
);
};
this is my live code:
https://stackblitz.com/edit/react-qotvwb?file=components/son_component.js
you're not using the formik handleChange at all.
I highlighted the changes that I made in https://stackblitz.com/
and you can test this working here