Skip to content

Migrate from Vuelidate

Migrating from Vuelidate is really simple. Regle API is similar to Vuelidate's one on purpose, so the mental model stays the same.

Regle type safety will ensure you make no mistakes while making the migration.

Imports

ts
import { useVuelidate } from '@vuelidate/core';
import { required } from '@vuelidate/validators';
import { useRegle } from '@regle/core';
import { required } from '@regle/rules';
ts
const v$ = useVuelidate(rules, state, options);
const { r$ } = useRegle(state, rules, options);

Helpers

ts
import { helpers } from '@vuelidate/validators';
import { withMessage, withParams, withAsync, isEmpty, ... } from '@regle/rules';

Helpers which have been renamed:

  • req -> isFilled
  • len -> getSize
  • regex -> matchRegex
  • forEach -> Deleted, you can use $each directly.
  • unwrap -> use toValue from Vue
    • Parameters are automatically unwrapped when using createRule

Displaying errors

Vuelidate:

vue
<template> 
  <p 
    v-for="error of v$.name.$errors"
    :key="error.$uid" 
  >
      {{error.$message}}
  </p>
</template>

Regle:

vue
<template>
  <p
    v-for="(error, index) of r$.$errors.name"
    :key="index"
  >
      {{ error }} 
  </p>
</template>

withMessage

Order of parameters are swapped

ts
const rule = helpers.withMessage('This field cannot be empty', required)
const rule = withMessage(required, 'This field cannot be empty')

withParams

You can create rules with parameters with createRule helper

ts
const contains = (param) =>
  helpers.withParams(
    { type: 'contains', value: param },
    (value) => !helpers.req(value) || value.includes(param)
  )

const contains = createRule({ 
  validator(value: Maybe<string>, param: Maybe<string>) { 
    return isEmpty(value) && value.includes(param); 
  }, 
  message: ({$params: [param]}) => `Value must contain ${param}`; 
})

Properties

Some properties have been renamed

Accessing nested fields

ts
v$.nested.child.$error
r$.nested.child.$error

Collections

See docs for validating arrays

ts
const v$ = useVuelidate({ 
  collection: { 
    $each: helpers.forEach({ 
      name: { 
        required
      } 
    }) 
  } 
}, {collection: [{name: ''}]})
const { r$ } = useRegle({ collection: [{name: ''}]}, { 
  collection: {
    $each: {
      name: {
        required
      }
    }
  }
})

Methods

See docs for type safe output

ts
const result = await v$.$validate();
const { valid, data } = await r$.$validate();

Custom messages

If you used to declare this kind of helper methods with Vuelidate:

ts
import {helpers, required, numeric, minLength} from '@vuelidate/validators';

export const requiredValidator = helpers.withMessage(
  'This field is required.',
  required
);
export const numericValidator = helpers.withMessage(
  'Please enter a valid value.',
  numeric
);

export const minLengthValidator = (value) =>
  helpers.withMessage(
    ({ $model, $params }) =>
      `Please enter a value greater than or equal to  ${$params.max}.`,
    minLength(value)
  );

You can remove it and configure it with global config.

TIP

If you use Nuxt , check the Nuxt module documentation for even easier error message sharing.

ts
import { 
defineRegleConfig
} from '@regle/core';
import {
withMessage
,
minLength
,
required
,
numeric
} from '@regle/rules';
const {
useRegle
:
useCustomRegle
} =
defineRegleConfig
({
rules
: () => ({
required
:
withMessage
(
required
, 'This field is required.'),
numeric
:
withMessage
(
numeric
, 'Please enter a valid value.'),
minLength
:
withMessage
(
minLength
, ({
$value
,
$params
: [
max
] }) => {
return `Minimum length is ${
max
}. Current length: ${
$value
?.
length
}`;
}) }) }) const {
r$
} =
useCustomRegle
({
name
: '' }, {
name
: {
required
,
numeric
,
minLength
:
minLength
(6)
} })

Nested component validation

Nested component validation is replaced by Scoped validation.

See docs for scoped validation for more details

ts
// [scoped-config.ts]
import { 
useScopedRegle
,
useCollectScope
,
useRegle
} from '@regle/core';
// Parent.vue const
v$
= useVuelidate();
const
v$
= useVuelidate({}, {}, {
$scope
: 'foo'});
const {
r$
} =
useCollectScope
();
const {
r$
} =
useCollectScope
('foo');
// Child.vue const
v$
= useVuelidate(validations, state);
const
v$
= useVuelidate(validations, state, {
$scope
: false });
const
v$
= useVuelidate(validations, state, {
$scope
: 'foo' });
const
v$
= useVuelidate(validations, state, {
$stopPropagation
: true });
const {
r$
} =
useScopedRegle
(state, validations);
const {
r$
} =
useRegle
(state, validations);
const {
r$
} =
useScopedRegle
(state, validations, {
namespace
: 'foo'});
const {
r$
} =
useScopedRegle
(state, validations);

Validation groups

ts
const rules = { 
  number: { isEven },
  nested: {
    word: { required: v => !!v }
  },
  $validationGroups: {
    firstGroup: ['number', 'nested.word']
  }
}
const v$ = useVuelidate(rules, ...);

const { r$ } = useRegle(..., { 
  number: {isEven},
  nested: {
    word: { required: v => !!v }
  }
}, {
  validationGroups: (fields) => ({
    firstGroup: [fields.number, fields.nested.word]
  })
})
r$.$groups.firstGroup

Released under the MIT License. Logo by Johannes Lacourly