web-dev-qa-db-fra.com

React Formik + Yup, onChange touchez le champ

Je voudrais afficher conditionnellement des erreurs dans mon formulaire.

Le fonctionnement de formik est que si vous modifiez un champ, toutes les validations sont exécutées et toutes les erreurs retournées même si vous n'en avez modifié qu'un seul.

Je voudrais afficher l'erreur uniquement si le champ a été touché et je voudrais qu'un champ soit touché lors d'un changement. La première modification du champ devrait le toucher.

Pour le moment, formik touche des champs juste sur soumettre. Comment pourrais-je le toucher sur Change?

Voici ma forme actuelle:

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
4
Lucian Tarna

Salut, je pense que ce n'est pas faisable onChange mais vous pouvez le faire lorsque l'entrée est floue et que vous devez utiliser la fonction handleBlur: onBlur={handleBlur}.

Les erreurs étant également un objet, vous ne pouvez l'afficher que lorsqu'un [input name] en a un.

Regardez quand les validations sont exécutées ici dans les documents: https://jaredpalmer.com/formik/docs/guides/validation#when-does-validation-run

3
t3__rry

Pour toucher un champ Formik sur Change, vous pouvez procéder comme suit:

<Formik
initialValues={initialValues}
onSubmit={(values) => {
    //submit form
}}>
{({ setFieldTouched, handleChange }) => {
    return (
        <Form>
            <Field
                name="type"
                onChange={e => {
                    setFieldTouched('type');
                    handleChange(e);
                }} />
        </Form>
    )
}}
3
Mudiaga Ejenavi

Une solution de contournement serait d'utiliser la méthode formik getFieldMeta et de passer le nom de votre champ et d'appeler la valeur prop qui n'est pas nulle lorsque vous tapez quelque chose.

errorMessage={
 formikProps.getFieldMeta("username").value
  ? formikProps.errors.username
   : ""
}
0
CLUTCHER