I would like to conditionally display errors in my form.
The way formik works is that if you change one field all validations are ran and all errors returned even thought you changed just one.
I would like to display the error only if the field was TOUCHED and I would like a field to be TOUCHED onChange. The first change to the field should make it touched.
At the moment formik is touching fields just on submit. How would I be able to touch it onChange?
This is my current form:
const optionsForSelect = (collection) => {
return collection.map(item => ({
value: item.id,
label: item.name
}))
}
const validationSchema = yup.object().shape({
length: yup
.number()
.min(1, 'Length should be a positive non-zero integer')
.required(),
frame_rate: yup
.string()
.required()
})
class SpecificationsForm extends React.PureComponent {
render() {
const {
values,
handleChange,
handleInputChange,
handleSelectChange,
handleBlur,
errors,
touched
} = this.props;
const debouncedHandleChange = debounce(handleChange, 200)
console.log(errors)
console.log('TOUCHED')
console.log(touched)
return (
<div className="panel panel-default specifications-panel" id="js-turbosquid-product-specifications-panel">
<div className="panel-heading">
<a href="#" className="js-more-info" data-toggle="collapse" data-target="#specifications-panel-instructions" tabIndex="-1">
Specifications
<i className="fa fa-question-circle" />
</a>
</div>
<div className="panel-body panel-collapse collapse in" id="specification-panel-body">
<div className="panel-body-container">
<div id="specifications-panel-instructions" className="panel-instructions collapse" />
<div className="row">
<div className="col-xs-6">
<PanelInputField
label='Length'
value={ values.length }
onChange={ (e) => handleInputChange(e, debouncedHandleChange) }
formName='turbosquid_product_form_length'
fieldName='length'
/>
<div className="form-field-error">{errors.length ? errors.length : "No Error"}</div>
<PanelSelectField
label='Frame Rate'
value={ values.frame_rate }
onChange={ ({value}) => handleSelectChange('frame_rate', value) }
formName='turbosquid_product_form_frame_rate'
fieldName='frame_rate'
options={ optionsForSelect(frameRateDropdownData) }
searchable={ false }
clearable={ false }
/>
</div>
<div className="col-xs-6">
<PanelCheckBox
label='Biped'
checked={ values.biped }
onChange={ (e) => handleInputChange(e, debouncedHandleChange) }
fieldName='biped'
formName='turbosquid_product_form_biped'
/>
<PanelCheckBox
label='Loopable'
checked={ values.loopable }
onChange={ (e) => handleInputChange(e, debouncedHandleChange) }
fieldName='loopable'
formName='turbosquid_product_form_loopable'
/>
</div>
</div>
</div>
</div>
</div>
)
}
}
const ProductSpecificationsMotionCapturePanel = withFormik({
validationSchema,
enableReinitialize: true,
mapPropsToValues: (props) => (props),
handleInputChange: (props) => (props.handleInputChange),
handleSelectChange: (props) => (props.handleSelectChange),
})(SpecificationsForm)
export default ProductSpecificationsMotionCapturePanel
To touch a Formik field onChange, you can do this:
<Formik
initialValues={initialValues}
onSubmit={(values) => {
//submit form
}}>
{({ setFieldTouched, handleChange }) => {
return (
<Form>
<Field
name="type"
onChange={e => {
setFieldTouched('type');
handleChange(e);
}} />
</Form>
)
}}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With