Skip to content

Instantly share code, notes, and snippets.

@nurdism
Created December 27, 2022 20:40
Show Gist options
  • Save nurdism/013dfc5deab80926da784e32c6067826 to your computer and use it in GitHub Desktop.
Save nurdism/013dfc5deab80926da784e32c6067826 to your computer and use it in GitHub Desktop.
Navigation guards for Inertia JS + vue 3 + typescript
import { onMounted, onBeforeUnmount } from 'vue'
interface GaurdStore {
beforeRouteLeave?: BeforeRouteLeave
afterRouteLeave?: AfterRouteLeave
}
export type RouterGuard = (event?: BeforeUnloadEvent) => boolean | undefined
export type ConfirmGuard = (options?: any, event?: MouseEvent) => Promise<boolean | undefined> | boolean | undefined
export type BeforeRouteLeave = { guard: RouterGuard; confirm: ConfirmGuard }
export type AfterRouteLeave = (options?: any, event?: MouseEvent) => void
const gaurds: GaurdStore = {}
export function getRouteGuard(type: keyof GaurdStore): AfterRouteLeave | BeforeRouteLeave | undefined {
return gaurds[type] ? gaurds[type] : undefined
}
export function onBeforeRouteLeave(guard: RouterGuard, confirm: ConfirmGuard): void {
const onBeforeUnload = (event: BeforeUnloadEvent) => {
if (gaurds.beforeRouteLeave && gaurds.beforeRouteLeave.guard(event) == true) {
event.preventDefault()
event.returnValue = ''
}
}
onBeforeUnmount(() => {
window.removeEventListener('beforeunload', onBeforeUnload)
delete gaurds.beforeRouteLeave
})
onMounted(() => {
gaurds.beforeRouteLeave = { guard, confirm }
window.addEventListener('beforeunload', onBeforeUnload)
})
}
export function onAfterRouteLeave(guard: RouterGuard): void {
onBeforeUnmount(() => {
delete gaurds.afterRouteLeave
})
onMounted(() => {
gaurds.afterRouteLeave = guard
})
}
<script lang="ts" setup>
import { onBeforeRouteLeave } from '~/components/router.ts'
const dirty = ref(false)
onBeforeRouteLeave(
() => dirty.value,
async () => {
return window.confirm("Do you really want to leave?")
},
)
</script>
<template>
<h1>Test</h1>
<AppLink :href="route('home')">App Link</AppLink>
<a href="https://google.com/">Google</a>
</template>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment