> ## Documentation Index
> Fetch the complete documentation index at: https://inertiajs-vi.tuantq.online/llms.txt
> Use this file to discover all available pages before exploring further.

# Validation

## Cách hoạt động

Việc xử lý lỗi validation phía máy chủ trong Inertia khác với form truyền thống điều khiển bằng XHR, nơi bạn phải bắt lỗi validation từ response `422` và tự cập nhật trạng thái lỗi của form — bởi Inertia không bao giờ nhận response `422`. Thay vào đó, Inertia hoạt động gần giống việc submit form tải toàn bộ trang thông thường. Cách thức như sau:

Trước tiên, bạn [gửi form bằng Inertia](/v3/the-basics/forms). Nếu có validation error phía server, bạn không trả các lỗi đó bằng JSON response `422`. Thay vào đó, server redirect người dùng về trang form trước đó và flash validation error vào session. Một số framework như Laravel tự động thực hiện việc này.

Tiếp theo, bất cứ khi nào các lỗi validation này tồn tại trong session, chúng sẽ tự động được chia sẻ với Inertia và trở thành page props ở phía client để bạn hiển thị trong form. Vì props có tính reactive, lỗi sẽ tự động được hiển thị khi quá trình submit form hoàn tất.

Cuối cùng, vì ứng dụng Inertia không bao giờ tạo response `422`, Inertia cần một cách khác để xác định response có chứa lỗi validation hay không. Inertia thực hiện việc này bằng cách kiểm tra object `page.props.errors` xem có lỗi nào tồn tại không. Nếu có lỗi, callback `onError()` của request sẽ được gọi thay cho callback `onSuccess()`.

## Chia sẻ lỗi

Để lỗi validation phía máy chủ có thể sử dụng ở phía client, framework phía máy chủ phải chia sẻ chúng thông qua prop `errors`. Các adapter chính thức của Inertia, chẳng hạn adapter Laravel, tự động thực hiện việc này. Với framework khác, bạn có thể phải tự cấu hình. Hãy tham khảo tài liệu của adapter phía máy chủ tương ứng để biết thêm thông tin.

## Hiển thị lỗi

Vì lỗi validation được cung cấp cho phía client dưới dạng props của page component, bạn có thể hiển thị có điều kiện dựa trên việc chúng có tồn tại hay không. Hãy nhớ rằng khi sử dụng các server adapter chính thức của Inertia (chẳng hạn adapter Laravel), prop `errors` sẽ tự động có sẵn trên trang.

<CodeGroup>
  ```vue Vue icon="vuejs" theme={null}
  <script setup>
  import { reactive } from "vue";
  import { router } from "@inertiajs/vue3";

  defineProps({ errors: Object });

  const form = reactive({
    first_name: null,
    last_name: null,
    email: null,
  });

  function submit() {
    router.post("/users", form);
  }
  </script>

  <template>
    <form @submit.prevent="submit">
      <label for="first_name">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">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">Email:</label>
      <input id="email" v-model="form.email" />
      <div v-if="errors.email">{{ errors.email }}</div>
      <button type="submit">Submit</button>
    </form>
  </template>
  ```

  ```jsx React icon="react" theme={null}
  import { useState } from "react";
  import { router, usePage } from "@inertiajs/react";

  export default function Edit() {
    const { errors } = usePage().props;

    const [values, setValues] = useState({
      first_name: null,
      last_name: null,
      email: null,
    });

    function handleChange(e) {
      setValues((values) => ({
        ...values,
        [e.target.id]: e.target.value,
      }));
    }

    function handleSubmit(e) {
      e.preventDefault();
      router.post("/users", values);
    }

    return (
      <form onSubmit={handleSubmit}>
        <label htmlFor="first_name">First name:</label>
        <input
          id="first_name"
          value={values.first_name}
          onChange={handleChange}
        />
        {errors.first_name && <div>{errors.first_name}</div>}
        <label htmlFor="last_name">Last name:</label>
        <input id="last_name" value={values.last_name} onChange={handleChange} />
        {errors.last_name && <div>{errors.last_name}</div>}
        <label htmlFor="email">Email:</label>
        <input id="email" value={values.email} onChange={handleChange} />
        {errors.email && <div>{errors.email}</div>}
        <button type="submit">Submit</button>
      </form>
    );
  }
  ```

  ```svelte Svelte icon="s" theme={null}
  <script>
      import { router } from '@inertiajs/svelte'

      let { errors = {} } = $props()

      let values = {
          first_name: null,
          last_name: null,
          email: null,
      }

      function handleSubmit() {
          router.post('/users', values)
      }
  </script>

  <form onsubmit={(e) => { e.preventDefault(); handleSubmit() }}>
      <label for="first_name">First name:</label>
      <input id="first_name" bind:value={values.first_name}>
      {#if errors.first_name}<div>{errors.first_name}</div>{/if}

      <label for="last_name">Last name:</label>
      <input id="last_name" bind:value={values.last_name}>
      {#if errors.last_name}<div>{errors.last_name}</div>{/if}

      <label for="email">Email:</label>
      <input id="email" bind:value={values.email}>
      {#if errors.email}<div>{errors.email}</div>{/if}

      <button type="submit">Submit</button>
  </form>
  ```
</CodeGroup>

Khi sử dụng adapter Vue, bạn cũng có thể truy cập lỗi thông qua object `$page.props.errors`.

### Nhiều lỗi cho mỗi field

Mặc định, adapter Laravel của Inertia chỉ trả lỗi validation đầu tiên cho mỗi field. Bạn có thể chọn nhận toàn bộ lỗi bằng cách đặt property `$withAllErrors` thành `true` trong middleware.

```php theme={null}
class HandleInertiaRequests extends Middleware
{
    protected $withAllErrors = true;

    // ...
}
```

Khi bật, mỗi field chứa một mảng chuỗi lỗi thay vì một chuỗi duy nhất.

<CodeGroup>
  ```vue Vue icon="vuejs" theme={null}
  <p v-for="error in errors.email">{{ error }}</p>
  ```

  ```jsx React icon="react" theme={null}
  {
    errors.email.map((error, index) => <p key={index}>{error}</p>);
  }
  ```

  ```svelte Svelte icon="s" theme={null}
  {#each errors.email as error}
      <p>{error}</p>
  {/each}
  ```
</CodeGroup>

Bạn có thể [cấu hình TypeScript](/v3/advanced/typescript#error-values) để mong đợi mảng thay vì chuỗi.

## Khôi phục dữ liệu input

Mặc dù cách xử lý lỗi trong Inertia tương tự submit form tải toàn bộ trang, Inertia còn mang lại nhiều lợi ích hơn. Thực tế, bạn thậm chí không cần tự điền lại dữ liệu input cũ của form.

Khi xảy ra validation error, người dùng thường được redirect về trang form trước đó. Mặc định, Inertia tự động giữ [component state](/v3/the-basics/manual-visits#state-preservation) cho request `post`, `put`, `patch` và `delete`. Vì vậy toàn bộ dữ liệu input cũ của form vẫn giữ nguyên như lúc người dùng gửi form.

Do đó, công việc còn lại duy nhất là hiển thị các lỗi validation bằng prop `errors`.

## Error bag

Nếu dùng [form helper](/v3/the-basics/forms#form-helper), bạn không cần dùng error bag vì validation error được tự động scope vào form object đã tạo request.

Với trang có nhiều form, có thể xảy ra xung đột khi hiển thị validation error nếu hai form dùng chung tên field. Ví dụ form "tạo công ty" và form "tạo người dùng" đều có field `name`. Vì cả hai đều hiển thị validation error `page.props.errors.name`, lỗi validation của field `name` ở một form sẽ xuất hiện trên cả hai form.

Để giải quyết vấn đề này, bạn có thể sử dụng "error bag". Error bag giới hạn phạm vi các lỗi validation được máy chủ trả về bên trong một key duy nhất dành riêng cho form đó. Tiếp tục ví dụ trên, bạn có thể dùng error bag `createCompany` cho form thứ nhất và `createUser` cho form thứ hai.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from "@inertiajs/vue3";

  router.post("/companies", data, {
    errorBag: "createCompany",
  });

  router.post("/users", data, {
    errorBag: "createUser",
  });
  ```

  ```js React icon="react" theme={null}
  import { router } from "@inertiajs/react";

  router.post("/companies", data, {
    errorBag: "createCompany",
  });

  router.post("/users", data, {
    errorBag: "createUser",
  });
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from "@inertiajs/svelte";

  router.post("/companies", data, {
    errorBag: "createCompany",
  });

  router.post("/users", data, {
    errorBag: "createUser",
  });
  ```
</CodeGroup>

Khi chỉ định error bag, các lỗi validation từ máy chủ sẽ được trả về tương ứng trong `page.props.errors.createCompany` và `page.props.errors.createUser`.

***

## Tài liệu chính thức

Bài dịch này được đối chiếu từ [tài liệu Inertia.js v3 chính thức](https://inertiajs.com/docs/v3/the-basics/validation). Nếu có khác biệt do phiên bản hoặc cập nhật mới, hãy ưu tiên tài liệu chính thức làm nguồn tham chiếu.
