admin管理员组

文章数量:1355555

I have this validation schema for a form made using withFormik() used in my React application, Here validateJql() is my custom validation function for yup

validationSchema: Yup.object().shape({
            rework: Yup.string().required("Rework query is required").validateJql(), 
            originalEstimate: Yup.string().required("Original Estimate query is required").validateJql()
        })

and my form Component is like this:

const addSomeForm = (props) => {
    const {
        values,
        touched,
        errors,
        isSubmitting,
        handleChange,
        handleSubmit,
    } = props;

return (
        <form onSubmit={handleSubmit}>
             <div className="form-group">
                  <div>
                      <label htmlFor="name" className="col-form-label"><b>Rework Query:</b></label>
                      <textarea id="query.rework" rows="5" type="text" className="form-control" placeholder="Enter JQL with aggregate Function" value={values.query.rework} onChange={handleChange} required />
                       {errors.query && errors.query.rework && touched.query && <span className="alert label"> <strong>{errors.query.rework}</strong></span>}
                   </div>
             </div>
             <div className="form-group">
                 <div>
                      <label htmlFor="name" className="col-form-label"><b>Original Estimate:</b></label>
                       <textarea id="query.originalEstimate" rows="5" type="text" className="form-control" placeholder="Enter JQL with aggregate Function" value={values.query.originalEstimate} onChange={handleChange} required />
                       {errors.query && errors.query.originalEstimate && touched.query && <span className="alert label"> <strong>{errors.query.originalEstimate}</strong></span>}
                 </div>
             </div>
       </form>
    )

Now, what I want to do is not to run validation on form submit if the field rework and originalEstimate is not touched and also not empty. How can I achieve this with withFormik HOC or Yup? I have partially been through Yup docs and Formik docs but could not find something to fit with my problem.

This is the case after submitting the form once and editing after that for minor tweaks in some of those multiple fields. if there are multiple fields and only some are edited, I don't want to run validation for all the fields existed.

Thank you in advance.

I have this validation schema for a form made using withFormik() used in my React application, Here validateJql() is my custom validation function for yup

validationSchema: Yup.object().shape({
            rework: Yup.string().required("Rework query is required").validateJql(), 
            originalEstimate: Yup.string().required("Original Estimate query is required").validateJql()
        })

and my form Component is like this:

const addSomeForm = (props) => {
    const {
        values,
        touched,
        errors,
        isSubmitting,
        handleChange,
        handleSubmit,
    } = props;

return (
        <form onSubmit={handleSubmit}>
             <div className="form-group">
                  <div>
                      <label htmlFor="name" className="col-form-label"><b>Rework Query:</b></label>
                      <textarea id="query.rework" rows="5" type="text" className="form-control" placeholder="Enter JQL with aggregate Function" value={values.query.rework} onChange={handleChange} required />
                       {errors.query && errors.query.rework && touched.query && <span className="alert label"> <strong>{errors.query.rework}</strong></span>}
                   </div>
             </div>
             <div className="form-group">
                 <div>
                      <label htmlFor="name" className="col-form-label"><b>Original Estimate:</b></label>
                       <textarea id="query.originalEstimate" rows="5" type="text" className="form-control" placeholder="Enter JQL with aggregate Function" value={values.query.originalEstimate} onChange={handleChange} required />
                       {errors.query && errors.query.originalEstimate && touched.query && <span className="alert label"> <strong>{errors.query.originalEstimate}</strong></span>}
                 </div>
             </div>
       </form>
    )

Now, what I want to do is not to run validation on form submit if the field rework and originalEstimate is not touched and also not empty. How can I achieve this with withFormik HOC or Yup? I have partially been through Yup docs and Formik docs but could not find something to fit with my problem.

This is the case after submitting the form once and editing after that for minor tweaks in some of those multiple fields. if there are multiple fields and only some are edited, I don't want to run validation for all the fields existed.

Thank you in advance.

Share Improve this question edited Feb 1, 2019 at 6:20 ShivaGaire asked Feb 1, 2019 at 5:55 ShivaGaireShivaGaire 2,8512 gold badges23 silver badges34 bronze badges 4
  • 1 Did you ever find a solution to this? – douglasrcjames Commented Jul 2, 2019 at 0:53
  • 1 Haven't found yet. Share with me too when you have found one – ShivaGaire Commented Jul 2, 2019 at 6:05
  • 1 My specific use case was solved with this: stackoverflow./questions/56844264/… – douglasrcjames Commented Jul 2, 2019 at 17:45
  • I'm facing the same issue... – Tom Commented Aug 26, 2019 at 6:41
Add a ment  | 

2 Answers 2

Reset to default 1

This is the default desired behavior as stated in formik docs but i think you can do the following:

Instead of using validationSchema, use validate function.

Validate function will work the same way your validationSchema works. You just need to use Yup programmatically from a function with mixed.validate

So you can have the full control of all the props in your form. You could also use the getFieldMeta to get the touched and value of the field and use that in your validation. Or get those props from touched object in form with getIn

Something like:


// Some util functions
function mapYupErrorsToFormikErrors(err: { inner: any[] }) {
  return err.inner
    .filter((i: { path: any }) => !!i.path)
    .reduce(
      (curr: any, next: { path: any; errors: any[] }) => ({
        ...curr,
        [next.path]: next.errors[0],
      }),
      {},
    )
}

function validateSchema(values: object, schema: Schema<object>) {
  return schema
    .validate(values, {
      abortEarly: false,
      strict: false,
    })
    .then(() => {
      return {}
    })
    .catch(mapYupErrorsToFormikErrors)
}


// Your validation function, as you are using `withFormik` you will have the props present

function validateFoo(values, props) {
  const { touched, value } = props.getFieldMeta('fooFieldName') // (or props.form.getFieldmeta, not sure)

  const errors = validateSchema(values, yourYupSchema)

  if (!touched && !value && errors.fooFieldName) {
    delete errors.fooFieldName
  } 

  return errors  
}

Well, touched might not work for your use case because formik probably would set it to true on submission, but there you have all the props and you can use something different, like the empty value or some other state prop you manually set. You got all the control there.

I had a similar issue, I ended up creating another field where I set the value when showing the edit screen. Then i pare inside a test function like this :

originalField: yup.string().default(''),

field: yup.string().default('').required('Field is required.').test('is-test',
    'This is my test.',
    async (value, $field) => {
      if($field.parent.originalField !== '' && value === $field.parent.originalField) return true
      return await plexAsyncValidation(value)
    }

Not perfect, but definitely working

本文标签: