> ## 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.

# Sự kiện

Inertia cung cấp một hệ thống sự kiện cho phép bạn "hook" vào nhiều sự kiện khác nhau trong lifecycle của thư viện.

## Đăng ký listener

Để đăng ký event listener, dùng phương thức `router.on()`.

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

  router.on("start", (event) => {
    console.log(`Starting a visit to ${event.detail.visit.url}`);
  });
  ```

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

  router.on("start", (event) => {
    console.log(`Starting a visit to ${event.detail.visit.url}`);
  });
  ```

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

  router.on("start", (event) => {
    console.log(`Starting a visit to ${event.detail.visit.url}`);
  });
  ```
</CodeGroup>

Bên dưới, Inertia dùng native browser event, nên bạn cũng có thể tương tác với Inertia event bằng các event method quen thuộc. Chỉ cần nhớ thêm tiền tố `inertia:` vào event name.

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

  document.addEventListener("inertia:start", (event) => {
    console.log(`Starting a visit to ${event.detail.visit.url}`);
  });
  ```

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

  document.addEventListener("inertia:start", (event) => {
    console.log(`Starting a visit to ${event.detail.visit.url}`);
  });
  ```

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

  document.addEventListener("inertia:start", (event) => {
    console.log(`Starting a visit to ${event.detail.visit.url}`);
  });
  ```
</CodeGroup>

## Gỡ listener

Khi bạn đăng ký event listener, Inertia tự động trả về một callback có thể gọi để gỡ listener đó.

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

  let removeStartEventListener = router.on("start", (event) => {
    console.log(`Starting a visit to ${event.detail.visit.url}`);
  });

  // Remove the listener...
  removeStartEventListener();
  ```

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

  let removeStartEventListener = router.on("start", (event) => {
    console.log(`Starting a visit to ${event.detail.visit.url}`);
  });

  // Remove the listener...
  removeStartEventListener();
  ```

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

  let removeStartEventListener = router.on("start", (event) => {
    console.log(`Starting a visit to ${event.detail.visit.url}`);
  });

  // Remove the listener...
  removeStartEventListener();
  ```
</CodeGroup>

Kết hợp với hook, bạn có thể tự động gỡ event listener khi component unmount.

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

  onUnmounted(
    router.on('start', (event) => {
      console.log(`Starting a visit to ${event.detail.visit.url}`)
    })
  )
  </script>
  ```

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

  useEffect(() => {
    return router.on("start", (event) => {
      console.log(`Starting a visit to ${event.detail.visit.url}`);
    });
  }, []);
  ```

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

  $effect(() => {
    return router.on("start", (event) => {
      console.log(`Starting a visit to ${event.detail.visit.url}`);
    });
  });
  ```
</CodeGroup>

Ngoài ra, nếu đang dùng event nguyên bản của trình duyệt, bạn có thể gỡ listener bằng `removeEventListener()`.

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

  let startEventListener = (event) => {
    console.log(`Starting a visit to ${event.detail.visit.url}`);
  };

  document.addEventListener("inertia:start", startEventListener);

  // Remove the listener...
  document.removeEventListener("inertia:start", startEventListener);
  ```

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

  let startEventListener = (event) => {
    console.log(`Starting a visit to ${event.detail.visit.url}`);
  };

  document.addEventListener("inertia:start", startEventListener);

  // Remove the listener...
  document.removeEventListener("inertia:start", startEventListener);
  ```

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

  let startEventListener = (event) => {
    console.log(`Starting a visit to ${event.detail.visit.url}`);
  };

  document.addEventListener("inertia:start", startEventListener);

  // Remove the listener...
  document.removeEventListener("inertia:start", startEventListener);
  ```
</CodeGroup>

## Listener chỉ chạy một lần

Bạn có thể đăng ký listener chỉ chạy một lần bằng phương thức `router.once()`. Listener tự động bị xóa sau lần gọi đầu tiên.

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

  router.once("start", (event) => {
    console.log(`Starting a visit to ${event.detail.visit.url}`);
  });
  ```

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

  router.once("start", (event) => {
    console.log(`Starting a visit to ${event.detail.visit.url}`);
  });
  ```

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

  router.once("start", (event) => {
    console.log(`Starting a visit to ${event.detail.visit.url}`);
  });
  ```
</CodeGroup>

Giống `router.on()`, phương thức này trả callback mà bạn có thể gọi để xóa listener trước khi nó chạy.

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

  let removeStartEventListener = router.once("start", (event) => {
    console.log(`Starting a visit to ${event.detail.visit.url}`);
  });

  // Remove the listener before it fires...
  removeStartEventListener();
  ```

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

  let removeStartEventListener = router.once("start", (event) => {
    console.log(`Starting a visit to ${event.detail.visit.url}`);
  });

  // Remove the listener before it fires...
  removeStartEventListener();
  ```

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

  let removeStartEventListener = router.once("start", (event) => {
    console.log(`Starting a visit to ${event.detail.visit.url}`);
  });

  // Remove the listener before it fires...
  removeStartEventListener();
  ```
</CodeGroup>

## Hủy event

Một số event như `before`, `networkError`, `httpException` và `location` hỗ trợ hủy, cho phép ngăn hành vi mặc định của Inertia. Giống native event, event sẽ bị hủy nếu chỉ cần một listener gọi `event.preventDefault()`.

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

  router.on("before", (event) => {
    if (!confirm("Are you sure you want to navigate away?")) {
      event.preventDefault();
    }
  });
  ```

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

  router.on("before", (event) => {
    if (!confirm("Are you sure you want to navigate away?")) {
      event.preventDefault();
    }
  });
  ```

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

  router.on("before", (event) => {
    if (!confirm("Are you sure you want to navigate away?")) {
      event.preventDefault();
    }
  });
  ```
</CodeGroup>

Để thuận tiện, nếu đăng ký event listener bằng `router.on()`, bạn có thể hủy event bằng cách trả về `false` từ listener.

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

  router.on("before", (event) => {
    return confirm("Are you sure you want to navigate away?");
  });
  ```

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

  router.on("before", (event) => {
    return confirm("Are you sure you want to navigate away?");
  });
  ```

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

  router.on("before", (event) => {
    return confirm("Are you sure you want to navigate away?");
  });
  ```
</CodeGroup>

Lưu ý browser không cho phép hủy native event `popstate`, vì vậy không thể ngăn history visit forward/back bằng Inertia.

## Before

Sự kiện `before` được phát ngay trước khi một request chuẩn bị được gửi đến máy chủ. Điều này hữu ích để chặn visit.

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

  router.on("before", (event) => {
    console.log(`About to make a visit to ${event.detail.visit.url}`);
  });
  ```

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

  router.on("before", (event) => {
    console.log(`About to make a visit to ${event.detail.visit.url}`);
  });
  ```

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

  router.on("before", (event) => {
    console.log(`About to make a visit to ${event.detail.visit.url}`);
  });
  ```
</CodeGroup>

Mục đích chính của sự kiện này là cho phép bạn ngăn một visit diễn ra.

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

  router.on("before", (event) => {
    return confirm("Are you sure you want to navigate away?");
  });
  ```

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

  router.on("before", (event) => {
    return confirm("Are you sure you want to navigate away?");
  });
  ```

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

  router.on("before", (event) => {
    return confirm("Are you sure you want to navigate away?");
  });
  ```
</CodeGroup>

## Start

Sự kiện `start` được phát khi request đến máy chủ đã bắt đầu. Sự kiện này hữu ích để hiển thị loading indicator.

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

  router.on("start", (event) => {
    console.log(`Starting a visit to ${event.detail.visit.url}`);
  });
  ```

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

  router.on("start", (event) => {
    console.log(`Starting a visit to ${event.detail.visit.url}`);
  });
  ```

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

  router.on("start", (event) => {
    console.log(`Starting a visit to ${event.detail.visit.url}`);
  });
  ```
</CodeGroup>

Sự kiện `start` không thể bị hủy.

## Progress

Sự kiện `progress` được phát khi tiến trình tăng lên trong quá trình tải file.

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

  router.on("progress", (event) => {
    this.form.progress = event.detail.progress.percentage;
  });
  ```

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

  router.on("progress", (event) => {
    this.form.progress = event.detail.progress.percentage;
  });
  ```

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

  router.on("progress", (event) => {
    this.form.progress = event.detail.progress.percentage;
  });
  ```
</CodeGroup>

Sự kiện `progress` không thể bị hủy.

## Success

Event `success` chạy khi page visit thành công, trừ khi có validation error. Tuy nhiên, điều này *không* bao gồm history visit.

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

  router.on("success", (event) => {
    console.log(`Successfully made a visit to ${event.detail.page.url}`);
  });
  ```

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

  router.on("success", (event) => {
    console.log(`Successfully made a visit to ${event.detail.page.url}`);
  });
  ```

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

  router.on("success", (event) => {
    console.log(`Successfully made a visit to ${event.detail.page.url}`);
  });
  ```
</CodeGroup>

Sự kiện `success` không thể bị hủy.

## Flash

Event `flash` chạy khi nhận [flash data](/v3/data-props/flash-data) từ server. Điều này hữu ích để hiển thị toast hoặc xử lý dữ liệu tạm thời tại một vị trí tập trung.

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

  router.on("flash", (event) => {
    if (event.detail.flash.toast) {
      showToast(event.detail.flash.toast);
    }
  });
  ```

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

  router.on("flash", (event) => {
    if (event.detail.flash.toast) {
      showToast(event.detail.flash.toast);
    }
  });
  ```

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

  router.on("flash", (event) => {
    if (event.detail.flash.toast) {
      showToast(event.detail.flash.toast);
    }
  });
  ```
</CodeGroup>

Event `flash` không thể bị hủy và được phát trên mọi response có chứa flash data.

## Error

Sự kiện `error` được phát khi có lỗi validation trong các page visit "thành công".

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

  router.on("error", (event) => {
    console.log(event.detail.errors);
  });
  ```

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

  router.on("error", (event) => {
    console.log(event.detail.errors);
  });
  ```

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

  router.on("error", (event) => {
    console.log(event.detail.errors);
  });
  ```
</CodeGroup>

Sự kiện `error` không thể bị hủy.

## HTTP Exception

Event `httpException` chạy khi nhận response không phải Inertia từ server, chẳng hạn HTML hoặc JSON response. Inertia response hợp lệ có header `X-Inertia` đặt thành `true` và JSON payload chứa [page object](/v3/core-concepts/the-protocol#the-page-object).

Event này chạy cho mọi loại response, bao gồm code `200`, `400` và `500`.

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

  router.on("httpException", (event) => {
    console.log(`An invalid Inertia response was received.`);
    console.log(event.detail.response);
  });
  ```

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

  router.on("httpException", (event) => {
    console.log(`An invalid Inertia response was received.`);
    console.log(event.detail.response);
  });
  ```

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

  router.on("httpException", (event) => {
    console.log(`An invalid Inertia response was received.`);
    console.log(event.detail.response);
  });
  ```
</CodeGroup>

Bạn có thể hủy event `httpException` để ngăn Inertia hiển thị modal response không phải Inertia.

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

  router.on("httpException", (event) => {
    event.preventDefault();

    // Handle the invalid response yourself...
  });
  ```

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

  router.on("httpException", (event) => {
    event.preventDefault();

    // Handle the invalid response yourself...
  });
  ```

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

  router.on("httpException", (event) => {
    event.preventDefault();

    // Handle the invalid response yourself...
  });
  ```
</CodeGroup>

## Network Error

Event `networkError` chạy khi xảy ra XHR error ngoài dự kiến như mất kết nối mạng. Ngoài ra event cũng chạy với error phát sinh khi resolve page component.

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

  router.on("networkError", (event) => {
    console.log(`An unexpected error occurred during an Inertia visit.`);
    console.log(event.detail.error);
  });
  ```

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

  router.on("networkError", (event) => {
    console.log(`An unexpected error occurred during an Inertia visit.`);
    console.log(event.detail.error);
  });
  ```

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

  router.on("networkError", (event) => {
    console.log(`An unexpected error occurred during an Inertia visit.`);
    console.log(event.detail.error);
  });
  ```
</CodeGroup>

Bạn có thể hủy event `networkError` để ngăn exception bị ném.

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

  router.on("networkError", (event) => {
    event.preventDefault();
    // Handle the error yourself
  });
  ```

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

  router.on("networkError", (event) => {
    event.preventDefault();
    // Handle the error yourself
  });
  ```

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

  router.on("networkError", (event) => {
    event.preventDefault();
    // Handle the error yourself
  });
  ```
</CodeGroup>

Event này *không* chạy với XHR request nhận response mức `400` và `500` hoặc response không phải Inertia, vì các tình huống đó được Inertia xử lý theo cách khác. Xem [tài liệu xử lý lỗi](/v3/advanced/error-handling) để biết thêm.

## Finish

Sự kiện `finish` được phát sau khi một request XHR hoàn tất, áp dụng cho cả response "thành công" lẫn "không thành công". Sự kiện này hữu ích để ẩn loading indicator.

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

  router.on("finish", (event) => {
    NProgress.done();
  });
  ```

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

  router.on("finish", (event) => {
    NProgress.done();
  });
  ```

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

  router.on("finish", (event) => {
    NProgress.done();
  });
  ```
</CodeGroup>

Sự kiện `finish` không thể bị hủy.

## Navigate

Sự kiện `navigate` được phát khi page visit thành công, cũng như khi điều hướng qua lịch sử trình duyệt.

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

  router.on("navigate", (event) => {
    console.log(`Navigated to ${event.detail.page.url}`);
  });
  ```

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

  router.on("navigate", (event) => {
    console.log(`Navigated to ${event.detail.page.url}`);
  });
  ```

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

  router.on("navigate", (event) => {
    console.log(`Navigated to ${event.detail.page.url}`);
  });
  ```
</CodeGroup>

Sự kiện `navigate` không thể bị hủy.

## Location

<Badge>v3.6.0+</Badge>

Event `location` chạy mỗi khi Inertia chuẩn bị ép full-page navigation, do [asset version](/v3/advanced/asset-versioning) thay đổi hoặc server trả redirect `Inertia::location()`. Event detail chứa boolean `versionChange` để phân biệt automatic asset version change với manual redirect.

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

  router.on("location", (event) => {
    console.log(`Navigating to ${event.detail.url}`);
    console.log(`Triggered by a version change: ${event.detail.versionChange}`);
  });
  ```

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

  router.on("location", (event) => {
    console.log(`Navigating to ${event.detail.url}`);
    console.log(`Triggered by a version change: ${event.detail.versionChange}`);
  });
  ```

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

  router.on("location", (event) => {
    console.log(`Navigating to ${event.detail.url}`);
    console.log(`Triggered by a version change: ${event.detail.versionChange}`);
  });
  ```
</CodeGroup>

Bạn có thể hủy event `location` để tự tiếp quản navigation, ví dụ hiển thị banner "có phiên bản mới" thay vì reload.

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

  router.on("location", (event) => {
    if (event.detail.versionChange) {
      event.preventDefault();
      showBanner("A new version is available.");
    }
  });
  ```

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

  router.on("location", (event) => {
    if (event.detail.versionChange) {
      event.preventDefault();
      showBanner("A new version is available.");
    }
  });
  ```

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

  router.on("location", (event) => {
    if (event.detail.versionChange) {
      event.preventDefault();
      showBanner("A new version is available.");
    }
  });
  ```
</CodeGroup>

## Prefetch

Event `prefetching` được kích hoạt khi router bắt đầu prefetch một trang.

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

  router.on("prefetching", (event) => {
    console.log(`Prefetching ${event.detail.visit.url}`);
  });
  ```

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

  router.on("prefetching", (event) => {
    console.log(`Prefetching ${event.detail.visit.url}`);
  });
  ```

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

  router.on("prefetching", (event) => {
    console.log(`Prefetching ${event.detail.visit.url}`);
  });
  ```
</CodeGroup>

Event `prefetching` không thể hủy.

## Prefetched

Event `prefetched` được kích hoạt khi router đã prefetch một trang thành công.

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

  router.on("prefetched", (event) => {
    console.log(`Prefetched ${event.detail.visit.url}`);
  });
  ```

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

  router.on("prefetched", (event) => {
    console.log(`Prefetched ${event.detail.visit.url}`);
  });
  ```

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

  router.on("prefetched", (event) => {
    console.log(`Prefetched ${event.detail.visit.url}`);
  });
  ```
</CodeGroup>

Event `prefetched` không thể hủy.

## Callback sự kiện

Ngoài các global event được mô tả trong trang này, Inertia còn cung cấp nhiều [event callback](/v3/the-basics/manual-visits#event-callbacks) chạy khi bạn thực hiện Inertia visit thủ công.

***

## 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/advanced/events). 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.
