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

<Warning>Bạn đang xem tài liệu Inertia.js v2. Inertia.js v3 đã được phát hành và hiện là phiên bản mặc định. Hãy xem [hướng dẫn nâng cấp](/v3/getting-started/upgrade-guide) để bắt đầu.</Warning>

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 sử dụng event nguyên bản của trình duyệt nên bạn cũng có thể tương tác với sự kiện Inertia bằng các phương thức event thông thường mà bạn đã quen dùng — chỉ cần nhớ thêm tiền tố `inertia:` vào tên sự kiện.

<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}
  import { router } from '@inertiajs/vue3'
  import { onUnmounted } from 'vue'

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

  ```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 4 icon="s" theme={null}
  import { router } from '@inertiajs/svelte'
  import { onMount } from 'svelte'

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

  ```js Svelte 5 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>

## Hủy sự kiện

Một số event như `before`, `exception` và `invalid` hỗ trợ hủy, cho phép bạn ngăn hành vi mặc định của Inertia. Tương tự event nguyên bản, event sẽ bị hủy nếu chỉ cần một event 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 ý, trình duyệt không cho phép hủy event nguyên bản `popstate`, vì vậy không thể ngăn các lần điều hướng tiến và lùi trong lịch sử khi sử dụng Inertia.js.

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

Sự kiện `success` được phát khi page visit thành công, trừ khi có lỗi validation. Tuy nhiên, điều này *không* bao gồm các visit trong lịch sử trình duyệt.

<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

<Badge>v2.3.3+</Badge>

Event `flash` được kích hoạt khi [flash data](/v2/data-props/flash-data) được nhận 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ể hủy. [Partial reload](/v2/data-props/partial-reloads) chỉ kích hoạt event nếu flash data đã thay đổi.

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

## Invalid

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

Sự kiện này được phát với mọi loại response, bao gồm các mã response `200`, `400` và `500`.

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

  router.on('invalid', (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('invalid', (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('invalid', (event) => {
      console.log(`An invalid Inertia response was received.`)
      console.log(event.detail.response)
  })
  ```
</CodeGroup>

Bạn có thể hủy sự kiện `invalid` để ngăn Inertia hiển thị modal chứa response không phải Inertia.

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

  router.on('invalid', (event) => {
      event.preventDefault()

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

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

  router.on('invalid', (event) => {
      event.preventDefault()

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

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

  router.on('invalid', (event) => {
      event.preventDefault()

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

## Exception

Sự kiện `exception` được phát khi xảy ra lỗi XHR ngoài dự kiến như gián đoạn mạng. Ngoài ra, sự kiện này cũng được phát với các lỗi xảy ra trong quá trình resolve page component.

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

  router.on('exception', (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('exception', (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('exception', (event) => {
      console.log(`An unexpected error occurred during an Inertia visit.`)
      console.log(event.detail.error)
  })
  ```
</CodeGroup>

Bạn có thể hủy sự kiện `exception` để ngăn lỗi bị ném ra.

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

  router.on('exception', (event) => {
      event.preventDefault()
      // Handle the error yourself
  })
  ```

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

  router.on('exception', (event) => {
      event.preventDefault()
      // Handle the error yourself
  })
  ```

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

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

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

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

## 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 event toàn cục được mô tả trong trang này, Inertia còn cung cấp một số [event callback](/v2/the-basics/manual-visits#event-callbacks) được kích hoạt 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 v2 chính thức](https://inertiajs.com/docs/v2/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.
