Yup required validation not working and not giving error for empty field - reactjs

I'm working on a form using formik and yup. I have added required schema, but it is not working. I can easily save having empty input fields. I have tried and googled but nothing worked.
I want to make it mandatory and it should give error if field is empty.
snippet of yup schema validation
opening_time: Yup.string().required("Opening time is Requried"),
closing_time: Yup.string().required("Closing time is Requried"),
address: Yup.string().required("Address is Requried"),
about: Yup.string().required("About is Required"),
Input field snippet
<div class="form-group mb-0">
<label>
About<span className="text-danger">*</span>
</label>
<textarea
name="about"
onChange={formik.handleChange}
value={formik.values.about}
class="form-control"
rows="5"
required
/>
{formik.touched.about && formik.errors.about ? (
<div className="err">
{formik.errors.about}
{console.log(formik.errors.about)}
</div>
) : null}
</div>

Try the following:
import React from 'react';
import { Formik, Form, Field } from 'formik';
import * as Yup from 'yup';
const SignupSchema = Yup.object().shape({
opening_time: Yup.string().required("Opening time is Requried"),
closing_time: Yup.string().required("Closing time is Requried"),
address: Yup.string().required("Address is Requried"),
about: Yup.string().required("About is Required"),
});
function ValidationSchemaExample() {
function updateDoctorProfile(e, values) {
console.log(`e: ${e}`);
console.log(`values: ${values}`)
}
return (
<div>
<h1>Signup</h1>
<Formik
initialValues={{
opening_time: "",
closing_time: "",
address: "",
about: "",
}}
validationSchema={SignupSchema}
onSubmit={values => {
// same shape as initial values
console.log(values);
}}
>
{({ values, errors, touched, handleChange, handleSubmit, isSubmitting }) => (
< div className="form-group mb-0">
<label>
About<span className="text-danger">*</span>
</label>
<textarea
name="about"
onChange={handleChange}
value={values.about}
className="form-control"
required
/>
<button type="submit" onClick={(e) => {
handleSubmit();
updateDoctorProfile(e, values);
}} disabled={isSubmitting}>
Submit
</button>
{touched.about && errors.about ? (
<div className="err">
{errors.about}
{console.log(errors.about)}
</div>
) : null}
</div>
)}
</Formik>
</div >
);
}
export default ValidationSchemaExample;
The only change is that the button tag's onClick attribute is passed the handleSubmit function along with your updateProfile function.

Related

Value type error message displaying instead of required error message on empty input submission

I'm using react-hook-form and yup together and for some reason it's displaying the wrong error message.
When the phone number input is left empty on submitting the form, it displays the typeError error message instead of the 'required' error message which I can't understand why that's happening since the input field is blank and there's no value to determine that it's of type 'number' or not.
import { yupResolver } from "#hookform/resolvers/yup";
import { useForm } from "react-hook-form";
import * as yup from "yup";
const schema = yup.object().shape({
name: yup.string().required("Field is required*"),
email: yup.string().email().required("Field is required*"),
phoneNumber: yup
.number()
.required("Field is required*") //this message should be displayed instead of typeError message
.typeError("Value must be a number*"),
message: yup.string().required("Please provide your message*")
});
export default function App() {
const {
reset,
register,
handleSubmit,
formState: { errors }
} = useForm({ resolver: yupResolver(schema) });
const submitForm = (data) => {
console.log(data);
reset();
};
return (
<div className="App">
<form className="contact-form" onSubmit={handleSubmit(submitForm)}>
<h2>Send Us a Message </h2>
<p>
<label for="name">Name</label>
<input name="name" type="text" {...register("name")} />
<p className="error-msg"> {errors.name?.message} </p>
</p>
<p>
<label for="email">Email</label>
<input name="email" type="text" {...register("email")} />
<p className="error-msg"> {errors.email?.message} </p>
</p>
<p>
<label for="phoneNumber">Phone</label>
<input
name="phoneNumber"
type="text"
{...register("phoneNumber")}
/>
</p>
<p className="error-msg"> {errors.phoneNumber?.message} </p>
<input type="submit" id="submit" />
</form>
</div>
);
Because Yup receives an empty string instead of a number, it thinks you're passing the wrong type. You need to tell RHF to return undefined if the input is empty:
<input
name="phoneNumber"
type="text"
{...register("phoneNumber", {
setValueAs: (v) => {
return v === "" ? undefined : parseInt(v, 10);
}
})}

In ReactJs using Formik library to handle form & Yup library

In ReactJs using formik library to handle form & Yup library for form validation rule, as i am trying to use "yup.array().of()" validator to validate array of fields (name, gender) which are passed from other component through props and i have stored this components in another component using accordion which is like the stepper, but it isn't working for me as i am not able to get the validation.
function FormBrowserG(props) {
const { intl } = props;
const peopleArray = props.peopleArrayValue;
//initial values
const initialValues = {
people: []
}
//creating the validation schema
const validationSchema = Yup.object().shape({
people: Yup.array().of(
Yup.object().shape({
name: Yup.string()
.required('Name is required'),
gender: Yup.string()
.required('gender is required')
})
)
});
//using useFormik
const formik = useFormik({
initialValues,
validationSchema,
onSubmit: (values) => {
}
});
const people = []
for (let index = 0; index < props.numberOfPeopleValue; index++) {
people.push(
<fieldset className="fieldset">
<legend className="legend">Person</legend>
<div className="display-flex">
<div className="formname">
<label className="gendername"><FormattedMessage id="AUTH.GENDER.LABEL" /></label>
<select
{...formik.getFieldProps('gender')}
className="form-control">
<option>Select</option>
<option key={10}>Male</option>
<option key={20}>Female </option>
</select>
{formik.touched.gender && formik.errors.gender ? (
<div className="warnings">{formik.errors.gender}</div>
) : null}
</div>
<div className="formo">
<label className="gendername"><FormattedMessage id="AUTH.SIGN_UP.NAME.LABEL" /></label>
<input
type="text"
id={`name${index}`}
className="name"
{...formik.getFieldProps(`name${index}`)}
required
/>
{formik.touched.name && formik.errors.name ? (
<div className="warnings">{formik.errors.name}</div>
) : null}
</div>
</div>
</fieldset>
)
}
return (
<>
<form onSubmit={formik.handleSubmit}>
<div className="row">
{people}
</div>
</form>
<div className="bofferingbtn">
<Link to={{
pathname: "/Confirmation",
state: value
}}>
<Button variant="contained" type="submit" className="obtn" size="large" color="primary" >
<FormattedMessage id="AUTH.OFFERING.BUTTON" />
</Button>
</Link>
</div>
</>
)
}
export default injectIntl(FormBrowserG)
You need to pass your values to formik like this -
initialValues={{ name: "", gender: "" }}
onSubmit={...}
//this will automatically validate the field
validationSchema={validationSchema}

Yup Was Not Working With Formik and also not provide any type of error

Yup Validation Not Working I Also tried Like This import Yup from 'yup' But Still Not Working.., when I create a simple validate Function without YUP it was worked fine. but when I use YUP that time Validation Not Work.
Added Form Component
import React from 'react';
import { useFormik } from 'formik';
import * as Yup from 'yup';
const initialValues = {
name : "",
surname : "",
address : ""
}
const validateSchema = Yup.object({
name: Yup.string().required('This Field is Required'),
surname: Yup.string().required('This Field is Required'),
address: Yup.string().required('This Field is Required')
});
const onSubmit = values =>{
console.log('FormData->',values);
}
function Form() {
const formik = useFormik({
initialValues ,
onSubmit ,
validateSchema
})
return (
<div className="container x col-md-4 col-md-offset-4" >
<form onSubmit={formik.handleSubmit} >
<div className="form-group">
<input autoComplete="off" onBlur={formik.handleBlur} onChange={formik.handleChange}
value={formik.values.name} name="name" className="name form-control-lg" placeholder="Enter A Name" />
<small>
{formik.touched.name && formik.errors.name ? <div className="error"> {formik.errors.name} </div> : null}
</small>
</div>
<div className="form-group">
<input autoComplete="off" onBlur={formik.handleBlur} onChange={formik.handleChange}
value={formik.values.surname} name="surname" className="surname form-control-lg" placeholder="Enter A Surname" />
<small> { formik.touched.surname && formik.errors.surname ? <div className="error"> {formik.errors.surname} </div> : null} </small>
</div>
<div className="form-group">
<input autoComplete="off" onBlur={formik.handleBlur} onChange={formik.handleChange} value={formik.values.address}
name="address" className="address form-control-lg" placeholder="Enter A Address" />
<small> {formik.touched.address && formik.errors.address ? <div className="error"> {formik.errors.address} </div> : null} </small>
</div>
<button className="btn btn-danger" >Submit</button>
</form>
</div>
)
}
export default Form;
The valid option here is validationSchema not validateSchema. Just set the right one:
const validationSchema = Yup.object({
// ...
});
useFormik({
// ...
validationSchema
})
To use formik and yup, first you have you do npm install yup and npm install formik. if your yarn user then do yarn add formik and yarn add yup.
after that follow this code.
import {Formik} from 'formik';
import * as yup from 'yup';
//functional component am using
export const Auth = () => {
const initialFormValue ={
email: '',password: '',};
const SignInSchema = yup.object().shape({
email: yup.string().email('Invalid Email').required('Email is Required'),
password: yup.string().min(5, 'Too Short').required('Password is Required'),
})
<Formik initialValues={initialFormValue} validationSchema={SignInSchema}
onSubmit={values => console.log(values)}>
{({values, errors, touched, handleChange, handleBlur,
handleSubmit,isSubmitting,
isValid}) => (
<>
<input name='email' type='email' handleChange={handleChange} value=
{values.email} onBlur={handleBlur} label='Email' />
{errors.email && touched.email ? (<Error>{errors.email}</Error>): null}
<input name='password' type='password' handleChange={handleChange} value=
{values.password} onBlur={handleBlur} label='Password' />
{errors.password && touched.password ? (<Error>{errors.password}</Error>):
null}
<button onClick={handleSubmit} type="submit">Send</button>
</>
) }
</Formik>
)}
its not necessary for you to define initial value outside you can do inside formik too <Formik initialValues={email: '', password: ''}> </Formik>
i hope this will help you thank you.

REACT.JS + FORMIK input field proble,

this is my first ever stack overflow question. I am trying to build a log-in page (making a full stack app with node express mongodb mongoose) and front end being REACT. I am running into an issue where the input field css does not register until I click into the input field and click out. I am using Formik to develop my form. I have two questions essentially: How can I fix this issue and how can I do an API call to my backend server which is running on localhost:3003. Here is the code:
import React from "react";
import "../App.css";
import { Formik } from "formik";
import * as EmailValidator from "email-validator";
import * as Yup from "yup";
const ValidatedLoginForm = () => (
<Formik
initialValues={{ email: "", password: "" }}
onSubmit={(values, { setSubmitting }) => {
setTimeout(() => {
console.log("Logging in", values);
setSubmitting(false);
}, 500);
}}
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="FormCenter">
<form onSubmit={handleSubmit} className="FormFields">
<div className="FormField">
<label htmlFor="email" className="FormField__Label">
Email
</label>
<input
name="email"
type="text"
placeholder="Enter your email"
value={values.email}
onBlur={handleBlur}
onChange={handleChange}
className={
errors.email && touched.email && "error" && "FormField__Input"
}
/>
{errors.email && touched.email && (
<div className="input-feedback">{errors.email}</div>
)}
</div>
<div className="FormField">
<label htmlFor="email" className="FormField__Label">
Password
</label>
<input
name="password"
type="password"
placeholder="Enter your password"
value={values.password}
onChange={handleChange}
onBlur={handleBlur}
className={
errors.password &&
touched.password &&
"error" &&
"FormField__Input"
}
/>
{errors.password && touched.password && (
<div className="input-feedback">{errors.password}</div>
)}
</div>
<div className="FormField">
<button
type="submit"
className="FormField__Button mr-20"
onChange
>
Login
</button>
</div>
</form>
</div>
);
}}
</Formik>
);
export default ValidatedLoginForm;
This looks like a normal behaviour to me. The validation in the form will get triggered when ,
when you submit the form
when the field is touched . Becoz of this you are seeing the error message being displayed when you switch between the fields without entering the values .
You should be firing the api call from the onSubmit, were you will get to access all the form values . I would suggest you to use fetch api . https://developer.mozilla.org/en/docs/Web/API/Fetch_API
Just make your onSubmit as a asyn method and fire your api call inside it .

Is it possible to timeout and hide the error message of forms after some time in Formik?

How can I hide the error message of forms after some time in Formik (React form library).
Is there any method in Formik?
It shows Name is Required, Email is required, Message is required. But I want to hide it after sometime.
Here is my code :
import React from 'react';
import { withFormik, Form, Field } from 'formik';
import * as Yup from 'yup';
import './contact.scss';
const Contact = ({ errors, touched }) => {
return (
<section className="c-section c-contact u-padding-v-xlarge">
<h1>Get in touch</h1>
<p>We&apos;ll love to hear from you!</p>
<Form>
<div>
{touched.name && errors.name ? (
<p style={{ color: 'red' }}>{errors.name}</p>
) : null}
<Field
id="Name"
type="text"
name="name"
autoComplete="name"
placeholder="Your Name"
/>
</div>
<div>
{touched.email && errors.email ? (
<p style={{ color: 'red' }}>{errors.email}</p>
) : null}
<Field
id="message"
type="email"
name="email"
autoComplete="email"
placeholder="Your Email"
/>
</div>
<div>
{touched.message && errors.message ? (
<p style={{ color: 'red' }}>{errors.message}</p>
) : null}
<Field
component="textarea"
name="message"
id="message"
placeholder="Your Message"
/>
</div>
<button type="submit" className="button button--success button--block">
Send Message
</button>
</Form>
</section>
);
};
export default withFormik({
mapPropsToValues: () => ({
name: '',
email: '',
message: '',
}),
validationSchema: Yup.object().shape({
name: Yup.string().required('Name is required'),
email: Yup.string()
.email('Email not valid')
.required('Email is required'),
message: Yup.string().required('Message is required'),
}),
handleSubmit: (values, { resetForm }) => {
// Handle http request here
console.log(values);
setTimeout(resetForm(), 2000);
},
})(Contact);
I have tried setTimeout(resetForm(), 2000); passing resetForm but it doesn't work. Any alternative?
When you do setTimeout(resetForm(), 2000) you are not passing the function (you are calling it) to the setTimeout. You should do setTimeout(resetForm, 2000). If you want to reset errors you can use setErrors like in example https://codesandbox.io/s/941jzvx01p

Resources