vee-validate icon indicating copy to clipboard operation
vee-validate copied to clipboard

Using global and local validators together

Open sttrbl opened this issue 2 years ago • 5 comments

Hi!

It is now possible to use either global validators in string and object syntax, or local validators in functional syntax.

<Field rules="required" />

<Field
  :rules="[
    (value) => value || 'Error',
    (value) => value > 2 || 'Error 2',
  ]"
/>

But is it somehow possible to use local and global validators together in :rules value? If not, then it would be cool to add such an opportunity, because personally in our project such a need arises often.

<!-- Something like this -->
<Field
  :rules="[
    'required',
    (value) => value || 'Error',
    (value) => value > 2 || 'Error 2',
  ]"
/>

Thanks!

sttrbl avatar Dec 26 '22 12:12 sttrbl

Not possible at the moment. However, I don't think it needs much work to get it working. I will see what I can do.

logaretm avatar Dec 30 '22 13:12 logaretm

Yes this would be very useful. I tried to do this today and it didn't work. If it sees one "Callable" rule in the array, then it tries to call all of them, which blows up for the global rules. I tried something like this:

:rules="['required', 'email', validateEmail]"

and it throws an error "Uncaught (in promise) TypeError: rule is not a function"

because it tries to call "required" (string) as a function.

isaackearl avatar Feb 15 '23 06:02 isaackearl

Isn't it 'better' to use a semi-standard already set by Vue in classes? e.g:

<label
    class="class-one class-two"
    :class="[
        computedClass,
        buttonClass,
        value === selectedValue || selectedValue === true
            ? 'checked'
             : '',
        ]"
/>

so something like this:

<Field
  rules='required|email'
  :rules="[
    (value) => value || 'Error',
    (value) => value > 2 || 'Error 2',
  ]"
/>

cas-technology avatar May 22 '23 15:05 cas-technology

@cas-technology Some rules do receive false as an argument, so turning them off with falsy values is risky.

logaretm avatar May 27 '23 15:05 logaretm

I have added a global rule to execute local functions.

interface FieldValidationMetaInfo {
  field: string;
  name: string;
  label?: string;
  value: unknown;
  form: Record<string, unknown>;
  rule?: {
    name: string;
    params?: Record<string, unknown> | unknown[];
  };
}

type ValidationRuleFunction<TValue = unknown, TParams = unknown[] | Record<string, unknown>> = (
  value: TValue,
  params: TParams,
  context: FieldValidationMetaInfo
) => boolean | string | Promise<boolean | string>;

type Params =
  | {
      rule: ValidationRuleFunction;
    }
  | [rule: ValidationRuleFunction, ...params: unknown[]];

const local: ValidationRuleFunction<unknown, Params> = (value, params, context) => {
  if (Array.isArray(params)) {
    const [rule, ...otherParams] = params;
    return rule(value, otherParams, context);
  } else {
    const { rule, ...otherParams } = params;
    return rule(value, otherParams, context);
  }
};

//////////////////////////

defineRule('local', local);

<Field :rules="{
  local: localValidationRule,
  globalRule: true,
}" />

<Field :rules="{
  local: {
    rule: localValidationRule,
    otherParams: {},
  },
  globalRule: true,
}" />

mastrayer avatar Jun 21 '24 15:06 mastrayer