Search code examples
javascriptformsvue.jsantdvuelidate

How to set validate rules in vuelidate to have value same as a field of an object?


Let say I have a vue component with data like this:

  data: () => ({
    form: {
      old_password: {
        data: '',
        type: 'password',
        label: 'Old Password',
      },
      new_password: {
        data: '',
        type: 'password',
        label: 'New Password',
      },
      repeat_password: {
        data: '',
        type: 'password',
        label: 'New Password Confirmation',
      },
    },
  }),

The data is formatted in this way as I am using another plug-in, ant-design, to build the form, and therefore formatting the data in another way is not an option. The data field will be storing the actual data.

Then, I have the following validation rules set for vuelidate.

  validations: {
    form: {
      old_password: {
        data: { required },
      },
      new_password: {
        data: { required },
      },
      repeat_password: {
        data: { sameAsPassword: sameAs('new_password') },
      },
    },
  },

The required rules works, but the sameAsPassword rule is not working. It always return error, even I am sure I am inputting the same password. I guess it is not comparing to a correct field. How can I set the rule so that it is comparing to the correct field?


Solution

  • new_password is not a sibling of repeat_password.data. From the built in validator docs

    • Locator can be either a sibling property name or a function. When provided as a function, it receives the model under validation as argument and this is bound to the component instance so you can access all its properties and methods, even in the scope of a nested validation.

    So a function needs to be passed to sameAs:

    validations: {
        form: {
          old_password: {
            data: { required },
          },
          new_password: {
            data: { required },
          },
          repeat_password: {
            data: { 
              sameAsPassword: sameAs(function() {
                return this.form.new_password.data;
              }) 
            },
          },
        },
      },
    

    At the same time, for the this to be working inside the function, the data needed to be changed from arrow function to return data. i.e.

    data() {
        return {
          form: {
            old_password: {
              data: '',
              type: 'password',
              label: 'Old Password',
            },
            new_password: {
              data: '',
              type: 'password',
              label: 'New Password',
            },
            repeat_password: {
              data: '',
              type: 'password',
              label: 'New Password Confirmation',
            },
          },
        }
      },