Интеграция с VeeValidate

Для интеграции VeeValidate с Vuetify необходимо установить библиотеку и ее зависимости:

npm install vee-validate @vee-validate/rules @vee-validate/i18n

После установки подключение происходит в основном файле приложения (main.js или main.ts):

import { createApp } from 'vue';
import App from './App.vue';
import { Field, Form, ErrorMessage, defineRule, configure } from 'vee-validate';
import * as rules from '@vee-validate/rules';
import { localize } from '@vee-validate/i18n';
import vuetify from './plugins/vuetify';

Object.keys(rules).forEach(rule => {
  defineRule(rule, rules[rule]);
});

configure({
  generateMessage: localize('ru'),
  validateOnInput: true,
});

const app = createApp(App);

app.component('VForm', Form);
app.component('VField', Field);
app.component('ErrorMessage', ErrorMessage);

app.use(vuetify).mount('#app');
  • defineRule — регистрация правил валидации.
  • configure — глобальная конфигурация сообщений и поведения валидации.
  • Компоненты Form, Field, ErrorMessage регистрируются для использования в шаблонах Vue.

Использование VeeValidate с компонентами Vuetify

Для корректной работы с компонентами Vuetify (v-text-field, v-select, v-checkbox) необходимо привязать валидацию через v-model и события input. Основной шаблон выглядит так:

<VForm @submit="handleSubmit">
  <VField name="email" rules="required|email" v-slot="{ field, errors }">
    <v-text-field
      v-bind="field"
      label="Email"
      :error="errors.length > 0"
      :error-messages="errors"
    />
  </VField>

  <VField name="password" rules="required|min:8" v-slot="{ field, errors }">
    <v-text-field
      v-bind="field"
      type="password"
      label="Пароль"
      :error="errors.length > 0"
      :error-messages="errors"
    />
  </VField>

  <v-btn type="submit" color="primary">Войти</v-btn>
</VForm>
  • v-slot=“{ field, errors }” — позволяет получить объект field, который содержит value и события onInput, и массив errors.
  • v-bind=“field” — связывает поле Vuetify с внутренними событиями и значением VeeValidate.
  • :error и :error-messages — управляют отображением ошибок в компонентах Vuetify.

Работа с кастомными компонентами и динамическими правилами

Если используется кастомный компонент, необходимо передавать modelValue и событие update:modelValue для корректной синхронизации с VeeValidate:

<VField name="username" rules="required|min:3" v-slot="{ field, errors }">
  <custom-input
    v-model="field.value"
    :error="errors.length > 0"
    :error-messages="errors"
  />
</VField>

Динамическая установка правил валидации:

<VField
  name="phone"
  :rules="phoneRequired ? 'required|numeric' : 'numeric'"
  v-slot="{ field, errors }"
>
  <v-text-field
    v-bind="field"
    label="Телефон"
    :error="errors.length > 0"
    :error-messages="errors"
  />
</VField>
  • Значение rules может изменяться реактивно, что позволяет включать или отключать обязательность полей.

Валидация форм и обработка ошибок

Для проверки всей формы используется метод validate() из VeeValidate:

import { useForm } from 'vee-validate';

setup() {
  const { handleSubmit, validate } = useForm();

  const onSub mit = handleSubmit(values => {
    console.log('Данные формы:', values);
  });

  const checkForm = async () => {
    const result = await validate();
    if (!result.valid) {
      console.log('Ошибки формы:', result.errors);
    }
  };

  return { onSubmit, checkForm };
}
  • handleSubmit — оборачивает функцию отправки и передает валидные данные.
  • validate() — возвращает объект с valid и errors, что позволяет программно управлять логикой формы.

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

VeeValidate поддерживает локализацию через @vee-validate/i18n. Для русского языка:

import { localize } from '@vee-validate/i18n';
import ru from '@vee-validate/i18n/dist/locale/ru.json';

configure({
  generateMessage: localize({ ru }),
  validateOnInput: true,
});
  • Каждое правило будет выводить сообщения на русском языке.
  • Можно создавать свои кастомные сообщения для отдельных полей:
configure({
  generateMessage: localize({
    ru: {
      messages: {
        required: 'Поле {field} обязательно для заполнения',
      },
    },
  }),
});

Интеграция с динамическими формами Vuetify

Для форм, где количество полей динамическое (например, массив контактов), VeeValidate позволяет использовать FieldArray:

<template>
  <VForm @submit="onSubmit">
    <div v-for="(contact, index) in contacts" :key="index">
      <VField :name="`contacts[${index}].email`" rules="required|email" v-slot="{ field, errors }">
        <v-text-field
          v-bind="field"
          label="Email контакта"
          :error="errors.length > 0"
          :error-messages="errors"
        />
      </VField>
    </div>
    <v-btn type="submit">Отправить</v-btn>
  </VForm>
</template>

<script>
import { reactive } from 'vue';

export default {
  setup() {
    const contacts = reactive([{ email: '' }, { email: '' }]);

    const onSub mit = values => {
      console.log(values);
    };

    return { contacts, onSubmit };
  },
};
</script>
  • Использование шаблонных строк в name позволяет привязать правила к массиву полей.
  • Ошибки отображаются индивидуально для каждого элемента массива.

Стилизация ошибок и визуальное соответствие Vuetify

Для единообразного отображения ошибок в компонентах Vuetify рекомендуется использовать:

.v-input .v-messages__message {
  color: red;
  font-size: 0.875rem;
}
  • Сообщения от VeeValidate интегрируются в стандартные элементы Vuetify (v-messages).
  • Можно использовать слоты Vuetify для кастомного отображения ошибок, например через append или prepend-inner.

Взаимодействие с кнопкой отправки

Для блокировки кнопки при наличии ошибок:

<v-btn
  type="submit"
  color="primary"
  :disabled="!formIsValid"
>
  Отправить
</v-btn>
import { useForm } from 'vee-validate';

setup() {
  const { meta } = useForm();
  const formIsValid = computed(() => meta.value.valid);

  return { formIsValid };
}
  • meta.valid обновляется автоматически при изменении полей.
  • Обеспечивает динамическое включение/отключение кнопки без дополнительной логики.