Yup: how to validate that a field is the same as another?

Created on 5 Jun 2017  Â·  15Comments  Â·  Source: jquense/yup

How can I have rules to validate that the user wrote the same account and confirmedAccount?

const inst = yup.object({
  account: yup.string().min(7).required(),
  confirmedAccount: yup.string().oneOf([yup.ref('account')])
 });
inst.validate({ account: '123456', confirmedAccount: '234' }, {
    abortEarly: false
}).then(function() { 
    console.log('ok', arguments);
})
.catch(function(error) {
    console.log('failed', error);
});

console.log(inst.cast({ account: '123456', confirmedAccount: '234' }));

Looks like yup.ref only works for casting data, not for validations?
So, how can I validate it?

Most helpful comment

FYI: I created this extended validation that looks working:

function equalTo(ref, msg) {
    return this.test({
        name: 'equalTo',
        exclusive: false,
    message: msg || '${path} must be the same as ${reference}',
        params: {
            reference: ref.path
        },
        test: function(value) {
      return value === this.resolve(ref) 
        }
    })
};

yup.addMethod(yup.string, 'equalTo', equalTo);


 const inst = yup.object({
   account: yup.string().min(7).required(),
   confirmedAccount: yup.string().equalTo(yup.ref('account'))
 });

inst.validate({ account: '1234567', confirmedAccount: '12345678' }, {
    abortEarly: false
}).then(function() { 
    console.log('ok', arguments);
})
.catch(function(error) {
    console.log('failed', error);
})

All 15 comments

FYI: I created this extended validation that looks working:

function equalTo(ref, msg) {
    return this.test({
        name: 'equalTo',
        exclusive: false,
    message: msg || '${path} must be the same as ${reference}',
        params: {
            reference: ref.path
        },
        test: function(value) {
      return value === this.resolve(ref) 
        }
    })
};

yup.addMethod(yup.string, 'equalTo', equalTo);


 const inst = yup.object({
   account: yup.string().min(7).required(),
   confirmedAccount: yup.string().equalTo(yup.ref('account'))
 });

inst.validate({ account: '1234567', confirmedAccount: '12345678' }, {
    abortEarly: false
}).then(function() { 
    console.log('ok', arguments);
})
.catch(function(error) {
    console.log('failed', error);
})

ah yeah I should note that in the documentation ,but yes that's the correct way to do it.

I already posted (accidentally) here: https://github.com/jaredpalmer/formik/issues/90#issuecomment-354868564

To repeat my question: Did anything change in the way how ref() or resolve() works? It doesn't work for me (see linked issue comment).

@vuhrmeister make sure you aren't using an arrow function for test:, nothing has changed, but it sounds like you getting schema.resolve which is a different method from test.resolve

Oh man … it can be so easy :)
Thanks, that was the point.

Anyhow: the docs doesn't say anything about test.resolve. Also I think the part about ref could be a bit more extended, maybe some examples. I don't think ref is such a rare use case.

happy to take some doc PR's :)

what is going on here i'm not getting ref value any ideas? https://codesandbox.io/s/zqlj1qp03p?expanddevtools=1

@trisox refs work for sibilings and child paths, they can't walk up to parents

@jquense / @jaredpalmer ah oke any tips for that?


i gave the whole object that needed to be validated as context...

https://github.com/mariocasciaro/object-path
then doing objectPath.get(this.options.context, ref.path) returns parent value.

https://github.com/jquense/yup/issues/49#issuecomment-393100970 has a solution:

password: yup.string().required('Password is required'),
confirmPassword: yup.string().oneOf([yup.ref('password'), null], "Passwords don't match").required('Confirm Password is required'),

where exactly can I add Yup.addmethod

I am not able to figure out how to add this Yup.addmethod and validate can some one help me Thanks

Below Code is written in single component file component.js Just looking how to compare fields by using addmethod

class Component extends React.Componenet {
render (){
return (

)
}
}

const formikEnhancer =withFormik({
validSchem :Yup.object().shape({
field1:Yup.string.required(),
field2:Yup.string.required()
}
})

const MyForm =props => {
const {
values,
touched,
dirty,
errors,
handleChange,
handleBlur,
handleSubmit,
handleReset,
setFieldValue,
setFieldTouched,
isSubmitting
} = props;
return (


/code for UI/

);
};
const MyEnhancedForm =formikEnhancer(MyForm);

export default connect (component);

Solution provided in #97 comment no longer works.

In the message parameter, ${path} and ${reference} need .this in front or node throws a Reference error that path (or reference) is not defined.

When this. is added, the error message returns undefined must be the same as undefined, not the desired confirmedAccount must be equal to account.

see related post on stack overflow.

Was having issues with the solution provided in this comment

Fixed this by adding a test:

  passwordValidation: yup
    .string()
    .test(
      'equal',
      'Passwords do not match!',
      function(v) { // Don't use arrow functions
        const ref = yup.ref('password');
        return v !== this.resolve(ref);
      }
    )

Works on v0.28.4 with formik 2.1.4

This was really helpful!! Thanks

Was this page helpful?
0 / 5 - 0 ratings