Перейти к содержимому

Валидация форм (Regle)

Формы валидируются на Regle — тайп-сейф headless-библиотеке для Vue 3 (модуль Regle для Nuxt). useRegle и обёртки withMessage/withAsync/withParams — автоимпорты; правила — из набора Regle rules.

Живая форма

Адрес проверяется на занятость

Необязательно, до 200 символов

Мост useFormField

Мост между Regle и core-формами — композабл useFormField: разворачивает статус поля r$ в плоское состояние error/invalid/pending/dirty. Ошибка идёт единственным каналом — prop error контрола; CoreFormGroup получает только label/hint/required.

VUE
<script setup lang="ts">
import { email, maxLength, required } from '@regle/rules'

const form = reactive({ email: '', comment: '' })

const { r$ } = useRegle(form, {
  email: { required, email, minLength: minLength(3) },
  comment: { maxLength: maxLength(200) },
})

const email = useFormField(r$, 'email')
const comment = useFormField(r$, 'comment')

const pending = computed(() => [email, comment].some(field => field.pending))

async function onSubmit() {
  const { valid, data } = await r$.$validate()
  if (!valid) return
  // data — тайп-сейф: required-поля непустые
  useNotices().push({ type: 'success', title: t('…'), message: t('…') })
}
</script>

<template>
  <form @submit.prevent="onSubmit">
    <CoreFormGroup :label="t('form.email')" required>
      <template #default="{ describedBy }">
        <CoreInput
          v-model="form.email"
          type="email"
          :error="email.error"
          :described-by="describedBy"
        />
      </template>
    </CoreFormGroup>
    <CoreButton type="submit" :loading="pending">
      {{ t('form.submit') }}
    </CoreButton>
  </form>
</template>

Правило одного role="alert"

Текст ошибки рендерит контрол (role="alert" + aria-invalid); если передать error ещё и в CoreFormGroup, ошибка задвоится и скринридер озвучит её дважды. describedBy из слота группы связывает контрол с активным пояснением — всегда прокидывайте его в контрол.

Гейтинг ошибок

Чистое поле не орёт ошибкой на первый рендер. Ошибки появляются у правленых (dirty) полей или все сразу после r$.$validate(). $pending — тихий статус: сабмит блокируется через :loading кнопки, спиннер на поле не показывается.

Локализация сообщений

Сообщения required/email/minLength/maxLength уже локализованы глобально (app/regle-config.ts, ключи validation.*). Сообщение кастомного правила — на месте использования через withMessage(rule, t('…')). У поля с async-правилом Regle дебаунсит ввод на 200 мс — проверка запускается после остановки ввода.

TS
import { withAsync, withMessage } from '@regle/rules'

const rules = {
  email: {
    required,
    email,
    // withAsync принимает функцию-валидатор; withMessage — локализованный текст
    uniq: withMessage(
      withAsync(async value => value !== 'taken@d2n.dev'),
      t('validation.emailTaken'),
    ),
  },
}

Где посмотреть

Секции «Валидация через Regle» — в песочницах:

CoreInputCoreFormGroup