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

cytsunny picture cytsunny · May 7, 2019 · Viewed 7.3k times · Source

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?

Answer

kevin picture kevin · May 7, 2019

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',
        },
      },
    }
  },