1
votes

I have component FromTo that takes 2 Timepickers components and cross validate one Timepicker component (From) to another (To). To timepicker has a greater vee-validate cross-field rule applied to it that looks like this:

   extend("greater", {
     params:["target"],
     validate(value, {target}){

     let regex = new RegExp("\d{2}:\d{2}", "g");

     console.log("from is "+target);   // prints @from instead of @from value
     console.log("value is "+value);

      return regex.test(value)
       &&  regex.test(target)
       &&  value > target; 

    },
     message: "To field must be greater that from field"
 });

Component body looks like this

<ValidationObserver>    
        <div class="flex mb-16 flex-wrap w-full">
            <div class="mr-1">
                <label class="font-bold block">From</label>
                <ValidationProvider name="from" rules="required|time" v-slot="{ errors }">
                    <VueTimepicker 
                        v-model="val.from"
                        close-on-complete
                        :input-class="['px-3', 'py-2', 'border', 'rounded', (errors.length ? 'border-red-400' : 'border-gray-400')]" 
                        />
                    <span class="text-sm w-40 block mt-1 text-red-400" v-if="errors.length"> {{ errors[0] }} </span>
                </ValidationProvider>
            </div>
            <div>
                <label class="font-bold block">To</label>
                <ValidationProvider name="to" rules="required|time|greater:@from" v-slot="{ errors }">
                    <VueTimepicker 
                        v-model="val.to" 
                        close-on-complete
                        :input-class="['px-3', 'py-2', 'border', 'rounded', (errors.length ? 'border-red-400' : 'border-gray-400')]"
                    />
                    <span class="text-sm w-40 block mt-1 text-red-400" v-if="errors.length"> {{ errors[0] }} </span>
                </ValidationProvider>
            </div>
        </div>
    </ValidationObserver>

I can see my rule being targeted but console logs @from instead of @from value. According to vee-validate docs in order for cross-field validation rule to work following criteria must be met:

Wrap the fields within the same ValidationObserver component. The target field must have a name or vid prop. Properly reference the target field name or vid value in the rules of the other.

I have also properly referenced from field

To reference another field's value, add a @ at the beginning of a param to signal to vee-validate that it should substitute the param with the target field value. So instead of getting a static "confirm" string, you will get the field's value instead.

I know I could possibly target static value like this:

rules=`required|time|greater:${this.from}`

But I would really want to target field values using @ sign. I 've simplified this example as I could and all the inner v-model bindings are correct. (from, to and entire component). I've been breaking my head around this for quite some time and red documentation carefully and would really appreciate any help...

1

1 Answers

2
votes

I changed your validation function to look like this:

extend("greater", {
  params: ["target"],
  validate(value, { target }) {
    let regex = new RegExp(/^\d{2}:\d{2}$/);

    return regex.test(value) && regex.test(target) && value > target;
  },
  message: "To field must be greater that from field"
});

The main thing is not adding the "g" because it doesn't do what you want here. Beyond that, I think your only real error is which version of vee-validate you're using. If you use the latest (3.2.0), your code mostly works and it certainly passes the value of "@from" not that string.

See here for a working example based off your code: https://codesandbox.io/s/veevalidate-30-cross-field-validation-9nebh

I removed the "time" validator because your greater validator seems to do the same thing already, and I didn't have the code for it anyways.