When I use Formik and Yup for validating the form, it only validates the main input fields when I click on the submit button. It works when I focus on the fields and then click somewhere else, triggering the validation on blur. However, when I click on submit, it does not validate the child fields.
const validationSchema = Yup.object().shape({
complaintType: Yup.string().required('Please select a payment type'),
fullName: Yup.string().required('Please Enter FullName'),
accountNo: Yup.string()
.required('Please Enter Account No')
.matches(/^\d+$/, 'Account number must contain only numbers')
.matches(
/^(?:\d{11}|\d{12}|\d{14})$/,
'Account number must be 11, 12, or 14 digits'
),
atm: Yup.object().when('complaintType', {
is: 'ATM',
then: () => Yup.object().shape({
atmId: Yup.string().required("Atm id is required"),
cardNumber: Yup.string().required('Card number is required'),
amount: Yup.number().required('Amount is required').positive('Amount must be positive'),
}),
otherwise: () => Yup.object(),
}),
});
this is my validation schema
const initialValues = {
complaintType: '',
fullName: '',
atm: {
cardNumber: '',
},
pos: {
debitedAmount: '',
billAmount: '',
},
};
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={(values) => {
console.log('Submitted values:', values);
}}
>
{({ values, errors, touched, handleChange }) => (
<Form>
<div className='row'>
<div className="col-md-6 col-sm-6 mb-3">
<label htmlFor="complaintType" className="form-label">Complaint Type:</label>
<Field as="select" name="complaintType" onChange={handleChange} className={`form-control text-center ${errors.complaintType && touched.complaintType ? 'error' : ''}`} style={{ borderColor: errors.accountNo && touched.accountNo ? 'red' : '' }}>
<option value="" disabled>-- Select Complaint --</option>
<option value="ATM">ATM COMPLAINT</option>
<option value="POS">POS (SHOPPING) COMPLAINT</option>
<option value="IMPS">IMPS COMPLAINT</option>
<option value="UPI">UPI COMPLAINT</option>
</Field>
{errors.complaintType && touched.complaintType && (
<div className="error-message" style={{ color: 'red' }}>{errors.complaintType}</div>
)}
</div>
</div>
<div className="col-md-4 col-sm-6 mb-3">
<div className='form-group'>
<label htmlFor='fullName' className='input-label'>Full Name</label>
<Field
id="fullName"
type="text"
name="fullName"
placeholder="Enter Full Name"
className={`form-control mt-1 ${errors.fullName && touched.fullName ? 'error' : ''}`}
style={{ borderColor: errors.fullName && touched.fullName ? 'red' : '' }}
/>
{errors.fullName && touched.fullName && (
<div className="error-message" style={{ color: 'red' }}>{errors.fullName}</div>
)}
</div>
</div>
{values.complaintType === 'ATM' && (
<>
<div className='row justify-content-center mb-4 h5'> ATM Complaint </div>
<div className='row'>
<div className="col-md-4 col-sm-6 mb-3">
<div className='form-group'>
<label htmlFor='atmCard' className='input-label'>cardNumber</label>
<Field
id="atmCard"
type="text"
name="atm.cardNumber"
placeholder="Enter Card Number"
className={`form-control mt-1 ${errors.atm && errors.atm.cardNumber && touched.atm && touched.atm.cardNumber ? 'error' : ''}`}
style={{ borderColor: errors.atm && errors.atm.cardNumber && touched.atm && touched.atm.cardNumber ? 'red' : '' }}
/>
{errors.atm && errors.atm.cardNumber && touched.atm && touched.atm.cardNumber && (
<div className="error-message" style={{ color: 'red' }}>{errors.atm.cardNumber}</div>
)}
</div>
</div>
</div>
</>
)}
<button type="submit" className="btn btn-primary">Submit Complaint</button>
</Form>
)}
</Formik>
I want the nested validation to occur dynamically when I select a dropdown option or change an input field. In other words, I need real-time validation to happen as I interact with the form.