> ## 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>Đây là tài liệu Inertia.js v1, phiên bản không còn được duy trì tích cực. Vui lòng tham khảo [tài liệu v3](/v3/getting-started/index).</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 2 icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue2'

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

  ```js Vue 3 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 2 icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue2'

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

  ```js Vue 3 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 2 icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue2'

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

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

  ```js Vue 3 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 2 icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue2'

  export default {
      mounted() {
          this.$once(
              'hook:destroyed',
              router.on('start', (event) => {
                  console.log(`Starting a visit to ${event.detail.visit.url}`)
              })
          )
      },
  }
  ```

  ```vue Vue 3 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}`)
      })
  }, [])
  ```

  ```svelte Svelte 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}`)
      })
  })
  ```
</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 2 icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue2'

  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 Vue 3 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ố sự kiện như `before`, `invalid` và `error` hỗ trợ việc 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ỉ một event listener gọi `event.preventDefault()`.

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

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

  ```js Vue 3 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 2 icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue2'

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

  ```js Vue 3 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 2 icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue2'

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

  ```js Vue 3 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 2 icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue2'

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

  ```js Vue 3 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 2 icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue2'

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

  ```js Vue 3 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 2 icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue2'

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

  ```js Vue 3 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 2 icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue2'

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

  ```js Vue 3 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.

## 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 2 icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue2'

  router.on('error', (errors) => {
      console.log(errors)
  })
  ```

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

  router.on('error', (errors) => {
      console.log(errors)
  })
  ```

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

  router.on('error', (errors) => {
      console.log(errors)
  })
  ```

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

  router.on('error', (errors) => {
      console.log(errors)
  })
  ```
</CodeGroup>

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

## Invalid

Sự kiện `invalid` được phát khi máy chủ trả về response không phải Inertia, chẳng hạn response HTML hoặc JSON thông thường. Một response Inertia hợp lệ là response có header `X-Inertia` được đặt thành `true` cùng payload `json` chứa [page object](/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 2 icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue2'

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

  ```js Vue 3 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 2 icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue2'

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

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

  ```js Vue 3 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 2 icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue2'

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

  ```js Vue 3 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 2 icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue2'

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

  ```js Vue 3 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>

Sự kiện này *không* được phát với request XHR nhận response mức `400` hoặc `500`, cũng không áp dụng cho response không phải Inertia, vì Inertia xử lý các tình huống này theo cơ chế khác. Hãy xem [tài liệu xử lý lỗi](/v1/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 2 icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue2'

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

  ```js Vue 3 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 2 icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue2'

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

  ```js Vue 3 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.

## Callback sự kiện

Ngoài các sự kiện toàn cục được mô tả trong trang này, Inertia còn cung cấp một số [event callback](/manual-visits#event-callbacks) được kích hoạt khi bạn chủ động thực hiện Inertia visit.

***

## 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 v1 chính thức](https://inertiajs.com/docs/v1/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.
