Валидация

Как это устроено

Обработка ошибок проверки на стороне сервера в Inertia работает немного иначе, чем в классической форме, управляемой ajax, где Вы отлавливаете ошибки проверки из ответов 422 и вручную обновляете состояние ошибки формы. Это потому, что Inertia никогда не получает ответов 422. Скорее, Inertia работает больше как стандартная отправка полностраничной формы. Вот как:

Сначала Вы отправляете форму с помощью Inertia. В случае ошибок проверки на стороне сервера Вы не сразу возвращаете эти ошибки в виде ответа JSON 422. Вместо этого Вы перенаправляете (на стороне сервера) обратно на страницу формы, на которой Вы находитесь, показывая ошибки проверки в сеансе. Такие фреймворки, как Laravel, делают это автоматически.

Затем, каждый раз, когда эти ошибки проверки присутствуют в сеансе, они автоматически передаются Inertia, делая их доступными на стороне клиента в качестве свойств страницы, которые Вы можете отобразить в своей форме. Поскольку свойства являются реактивными, они автоматически отображаются после завершения отправки формы.

Обмен ошибками

Для того, чтобы ошибки проверки на стороне сервера были доступны на стороне клиента, Ваша серверная инфраструктура должна делиться ими с помощью свойства errors. Некоторые адаптеры, такие как адаптер Laravel, делают это автоматически. Другим может потребоваться сделать это вручную. Пожалуйста, обратитесь к документации Вашего конкретного серверного адаптера для получения дополнительной информации.

class UsersController extends Controller
{
    public function create()
    {
        return Inertia::render('Users/Create');
    }

    public function store()
    {
      Request::validate([
          'first_name' => ['required', 'max:50'],
          'last_name' => ['required', 'max:50'],
          'email' => ['required', 'max:50', 'email'],
      ]);

      $user = User::create(
        Request::only('first_name', 'last_name', 'email')
      );

      return Redirect::route('users.show', $user);
    }
}

Отображение ошибок

Поскольку ошибки валидации становятся доступными на стороне клиента как свойства компонентов страницы, Вы можете отображать их в зависимости от их наличия. Вот как это сделать.

<template>
  <form @submit.prevent="submit">
    <label for="first_name">Имя:</label>
    <input id="first_name" v-model="form.first_name" />
    <div v-if="errors.first_name">{{ errors.first_name }}</div>
    <label for="last_name">Фамилия:</label>
    <input id="last_name" v-model="form.last_name" />
    <div v-if="errors.last_name">{{ errors.last_name }}</div>
    <label for="email">Эл. почта:</label>
    <input id="email" v-model="form.email" />
    <div v-if="errors.email">{{ errors.email }}</div>
    <button type="submit">Отправить</button>
  </form>
</template>

<script>
export default {
  props: {
    errors: Object,
  },
  data() {
    return {
      form: {
        first_name: null,
        last_name: null,
        email: null,
      },
    }
  },
  methods: {
    submit() {
      this.$inertia.post('/users', this.form)
    },
  },
}
</script>

Обратите внимание, что в адаптерах Vue Вы также можете получить доступ к ошибкам через объект $page.props.errors.

Повторное заполнение ввода

Хотя обработка ошибок в Inertia аналогична отправке полностраничных форм, этот подход на самом деле намного лучше, поскольку Вам не нужно вручную повторно заполнять старые входные данные формы.

При возникновении ошибок проверки пользователь автоматически перенаправляется обратно на страницу формы, на которой он уже находится. И по умолчанию Inertia автоматически сохраняет состояние компонента для запросов post, put, patch и delete. Это означает, что все входные данные старой формы остаются в точности как есть.

Единственное, что изменилось, - это свойство errors, которое теперь содержит ошибки валидации.

Устранение ошибок

Поскольку приложения Inertia никогда не генерируют ответы 422, Inertia необходим другой способ определить, содержит ли ответ ошибки проверки. Для этого Inertia проверяет объект page.props.errors на наличие ошибок. В случае появления ошибок будет вызван обратный вызов onError() вместо обратного вызова onSuccess().

Если Ваше приложение сообщает об ошибках, используя свойство, отличное от errors, Вы должны сообщить Inertia, как исправить эти ошибки. Это можно сделать с помощью обратного вызова resolveErrors(), применяемого на уровне адаптера.

import { createApp, h } from 'vue'
import { App, plugin } from '@inertiajs/inertia-vue3'

const el = document.getElementById('app')

createApp({
  render: () => h(App, {
    initialPage: JSON.parse(el.dataset.page),
    resolveComponent: name => require(`./Pages/${name}`).default,
    resolveErrors: page => (page.props.errors || {}),
  })
}).use(plugin).mount(el)

Обратите внимание, что обратный вызов resolveErrors() всегда должен возвращать объект, даже если ошибок нет.

Пакеты ошибок

Для страниц, содержащих более одной формы, могут возникнуть конфликты при отображении ошибок проверки, если две формы имеют одинаковые имена полей. Например, представьте себе форму «создать компанию» и форму «создать пользователя», у которых есть поле name. Поскольку обе формы будут отображать ошибку проверки page.props.errors.name, создание ошибки проверки для поля name в любой форме приведет к появлению ошибки в обеих формах.

Чтобы обойти это, Вы можете использовать пакеты ошибок. Пакеты ошибок охватывают ошибки проверки, возвращаемые сервером, в пределах уникального ключа, специфичного для этой формы. Продолжая наш пример выше, у Вас может быть пакет ошибок createCompany для первой формы и пакет ошибок createUser для второй формы.

Inertia.post('/companies', data, {
  errorBag: 'createCompany',
})

Inertia.post('/users', data, {
  errorBag: 'createUser',
})

Это приведет к тому, что ошибки проверки вернутся с сервера как page.props.errors.createCompany и page.props.errors.createUser.

Обратите внимание: если Вы используете помощник формы, нет необходимости использовать пакеты ошибок, поскольку ошибки проверки автоматически переносятся в область объекта формы.