Skip to content

Commit

Permalink
Add Global "Visit" Options Hook (#1052)
Browse files Browse the repository at this point in the history
* add global visit options hook
  • Loading branch information
claudiodekker authored Jan 19, 2022
1 parent a183c09 commit 20b7782
Show file tree
Hide file tree
Showing 14 changed files with 94 additions and 57 deletions.
13 changes: 7 additions & 6 deletions packages/inertia-react/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,12 @@ export interface InertiaFormProps<TForm = Record<string, any>> {
clearErrors: (...fields: (keyof TForm)[]) => void
setError(field: keyof TForm, value: string): void
setError(errors: Record<keyof TForm, string>): void
submit: (method: Inertia.Method, url: string, options?: Inertia.VisitOptions) => void
get: (url: string, options?: Inertia.VisitOptions) => void
patch: (url: string, options?: Inertia.VisitOptions) => void
post: (url: string, options?: Inertia.VisitOptions) => void
put: (url: string, options?: Inertia.VisitOptions) => void
delete: (url: string, options?: Inertia.VisitOptions) => void
submit: (method: Inertia.Method, url: string, options?: Inertia.VisitParams) => void
get: (url: string, options?: Inertia.VisitParams) => void
patch: (url: string, options?: Inertia.VisitParams) => void
post: (url: string, options?: Inertia.VisitParams) => void
put: (url: string, options?: Inertia.VisitParams) => void
delete: (url: string, options?: Inertia.VisitParams) => void
}

export function useForm<TForm = Record<string, any>>(initialValues?: TForm): InertiaFormProps<TForm>;
Expand Down Expand Up @@ -127,6 +127,7 @@ export type InertiaAppOptionsForCSR<SharedProps> = BaseInertiaAppOptions & {
id?: string,
page?: Inertia.Page|string,
render?: undefined,
visitOptions?: Inertia.VisitOptions,
setup(options: SetupOptions<HTMLElement, SharedProps>): CreateInertiaAppSetupReturnType
}

Expand Down
2 changes: 2 additions & 0 deletions packages/inertia-react/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export default function App({
resolveComponent,
titleCallback,
onHeadUpdate,
visitOptions,
}) {
const [current, setCurrent] = useState({
component: initialComponent || null,
Expand All @@ -36,6 +37,7 @@ export default function App({
key: preserveState ? current.key : Date.now(),
}))
},
visitOptions: visitOptions || (() => undefined),
})

Inertia.on('navigate', () => headManager.forceUpdate())
Expand Down
5 changes: 3 additions & 2 deletions packages/inertia-react/src/createInertiaApp.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import App from './App'
import { createElement } from 'react'

export default async function createInertiaApp({ id = 'app', resolve, setup, title, page, render }) {
export default async function createInertiaApp({ id = 'app', resolve, setup, title, visitOptions, page, render }) {
const isServer = typeof window === 'undefined'
const el = isServer ? null : document.getElementById(id)
const initialPage = page || JSON.parse(el.dataset.page)
Expand All @@ -19,6 +19,7 @@ export default async function createInertiaApp({ id = 'app', resolve, setup, tit
resolveComponent,
titleCallback: title,
onHeadUpdate: isServer ? elements => (head = elements) : null,
visitOptions,
},
})
})
Expand All @@ -28,7 +29,7 @@ export default async function createInertiaApp({ id = 'app', resolve, setup, tit
createElement('div', {
id,
'data-page': JSON.stringify(initialPage),
}, reactApp)
}, reactApp),
)

return { head, body }
Expand Down
5 changes: 3 additions & 2 deletions packages/inertia-svelte/src/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import Render, { h } from './Render.svelte'
import { Inertia } from '@inertiajs/inertia'
export let initialPage, resolveComponent
export let initialPage, resolveComponent, visitOptions
Inertia.init({
initialPage,
Expand All @@ -14,7 +14,8 @@
page,
key: preserveState ? current.key : Date.now()
}))
}
},
visitOptions,
})
$: child = $store.component && h($store.component.default, $store.page.props)
Expand Down
3 changes: 2 additions & 1 deletion packages/inertia-svelte/src/createInertiaApp.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import App from './App.svelte'

export default async function createInertiaApp({ id = 'app', resolve, setup, page, render }) {
export default async function createInertiaApp({ id = 'app', resolve, setup, visitOptions, page, render }) {
const isServer = typeof window === 'undefined'
const el = isServer ? null : document.getElementById(id)
const initialPage = page || JSON.parse(el.dataset.page)
Expand All @@ -17,6 +17,7 @@ export default async function createInertiaApp({ id = 'app', resolve, setup, pag
initialComponent,
resolveComponent,
onHeadUpdate: isServer ? elements => (head = elements) : null,
visitOptions,
},
})
})
Expand Down
13 changes: 7 additions & 6 deletions packages/inertia-vue/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export interface CreateInertiaAppProps {
title?: (title: string) => string
page?: Inertia.Page
render?: (vm: Vue) => Promise<string>
visitOptions?: Inertia.VisitOptions
}

export declare function createInertiaApp(props: CreateInertiaAppProps): Promise<{ head: string[], body: string } | void>
Expand Down Expand Up @@ -85,12 +86,12 @@ export interface InertiaFormProps<TForm> {
clearErrors(...fields: (keyof TForm)[]): this
setError(field: keyof TForm, value: string): this
setError(errors: Record<keyof TForm, string>): this
submit(method: string, url: string, options?: Partial<Inertia.VisitOptions>): void
get(url: string, options?: Partial<Inertia.VisitOptions>): void
post(url: string, options?: Partial<Inertia.VisitOptions>): void
put(url: string, options?: Partial<Inertia.VisitOptions>): void
patch(url: string, options?: Partial<Inertia.VisitOptions>): void
delete(url: string, options?: Partial<Inertia.VisitOptions>): void
submit(method: string, url: string, options?: Partial<Inertia.VisitParams>): void
get(url: string, options?: Partial<Inertia.VisitParams>): void
post(url: string, options?: Partial<Inertia.VisitParams>): void
put(url: string, options?: Partial<Inertia.VisitParams>): void
patch(url: string, options?: Partial<Inertia.VisitParams>): void
delete(url: string, options?: Partial<Inertia.VisitParams>): void
cancel(): void
}

Expand Down
6 changes: 6 additions & 0 deletions packages/inertia-vue/src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ export default {
required: false,
default: () => () => {},
},
visitOptions: {
type: Function,
required: false,
default: () => undefined,
},
},
data() {
return {
Expand All @@ -51,6 +56,7 @@ export default {
this.page = page
this.key = preserveState ? this.key : Date.now()
},
visitOptions: this.visitOptions,
})

Inertia.on('navigate', () => headManager.forceUpdate())
Expand Down
3 changes: 2 additions & 1 deletion packages/inertia-vue/src/createInertiaApp.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import App, { plugin } from './app'

export default async function createInertiaApp({ id = 'app', resolve, setup, title, page, render }) {
export default async function createInertiaApp({ id = 'app', resolve, setup, title, visitOptions, page, render }) {
const isServer = typeof window === 'undefined'
const el = isServer ? null : document.getElementById(id)
const initialPage = page || JSON.parse(el.dataset.page)
Expand All @@ -24,6 +24,7 @@ export default async function createInertiaApp({ id = 'app', resolve, setup, tit
resolveComponent,
titleCallback: title,
onHeadUpdate: isServer ? elements => (head = elements) : null,
visitOptions,
},
},
plugin,
Expand Down
1 change: 1 addition & 0 deletions packages/inertia-vue/src/link.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export default {
data.on = {
click: () => ({}),
cancelToken: () => ({}),
before: () => ({}),
start: () => ({}),
progress: () => ({}),
finish: () => ({}),
Expand Down
13 changes: 7 additions & 6 deletions packages/inertia-vue3/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export interface CreateInertiaAppProps {
title?: (title: string) => string
page?: Inertia.Page
render?: (app: VueApp) => Promise<string>
visitOptions?: Inertia.VisitOptions
}

export declare function createInertiaApp(props: CreateInertiaAppProps): Promise<{ head: string[], body: string } | void>
Expand Down Expand Up @@ -74,12 +75,12 @@ export interface InertiaFormProps<TForm> {
clearErrors(...fields: (keyof TForm)[]): this
setError(field: keyof TForm, value: string): this
setError(errors: Record<keyof TForm, string>): this
submit(method: string, url: string, options?: Partial<Inertia.VisitOptions>): void
get(url: string, options?: Partial<Inertia.VisitOptions>): void
post(url: string, options?: Partial<Inertia.VisitOptions>): void
put(url: string, options?: Partial<Inertia.VisitOptions>): void
patch(url: string, options?: Partial<Inertia.VisitOptions>): void
delete(url: string, options?: Partial<Inertia.VisitOptions>): void
submit(method: string, url: string, options?: Partial<Inertia.VisitParams>): void
get(url: string, options?: Partial<Inertia.VisitParams>): void
post(url: string, options?: Partial<Inertia.VisitParams>): void
put(url: string, options?: Partial<Inertia.VisitParams>): void
patch(url: string, options?: Partial<Inertia.VisitParams>): void
delete(url: string, options?: Partial<Inertia.VisitParams>): void
cancel(): void
}

Expand Down
8 changes: 7 additions & 1 deletion packages/inertia-vue3/src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,13 @@ export default {
required: false,
default: () => () => {},
},
visitOptions: {
type: Function,
required: false,
default: () => undefined,
},
},
setup({ initialPage, initialComponent, resolveComponent, titleCallback, onHeadUpdate }) {
setup({ initialPage, initialComponent, resolveComponent, titleCallback, onHeadUpdate, visitOptions }) {
component.value = initialComponent ? markRaw(initialComponent) : null
page.value = initialPage
key.value = null
Expand All @@ -51,6 +56,7 @@ export default {
page.value = args.page
key.value = args.preserveState ? key.value : Date.now()
},
visitOptions,
})

Inertia.on('navigate', () => headManager.forceUpdate())
Expand Down
3 changes: 2 additions & 1 deletion packages/inertia-vue3/src/createInertiaApp.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createSSRApp, h } from 'vue'
import App, { plugin } from './app'

export default async function createInertiaApp({ id = 'app', resolve, setup, title, page, render }) {
export default async function createInertiaApp({ id = 'app', resolve, setup, title, visitOptions, page, render }) {
const isServer = typeof window === 'undefined'
const el = isServer ? null : document.getElementById(id)
const initialPage = page || JSON.parse(el.dataset.page)
Expand All @@ -20,6 +20,7 @@ export default async function createInertiaApp({ id = 'app', resolve, setup, tit
resolveComponent,
titleCallback: title,
onHeadUpdate: isServer ? elements => (head = elements) : null,
visitOptions,
},
plugin,
})
Expand Down
70 changes: 41 additions & 29 deletions packages/inertia/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,34 @@ import { hasFiles } from './files'
import { objectToFormData } from './formData'
import { default as Axios, AxiosResponse } from 'axios'
import { hrefToUrl, mergeDataIntoQueryString, urlWithoutHash } from './url'
import { ActiveVisit, GlobalEvent, GlobalEventNames, GlobalEventResult, LocationVisit, Method, Page, PageHandler, PageResolver, PendingVisit, PreserveStateOption, RequestPayload, VisitId, VisitOptions } from './types'
import { ActiveVisit, GlobalEvent, GlobalEventNames, GlobalEventResult, LocationVisit, Method, Page, PageHandler, PageResolver, PendingVisit, PreserveStateOption, RequestPayload, VisitId, VisitParams, VisitOptions } from './types'
import { fireBeforeEvent, fireErrorEvent, fireExceptionEvent, fireFinishEvent, fireInvalidEvent, fireNavigateEvent, fireProgressEvent, fireStartEvent, fireSuccessEvent } from './events'

const isServer = typeof window === 'undefined'

export class Router {
protected page!: Page
protected resolveComponent!: PageResolver
protected swapComponent!: PageHandler
protected visitOptions!: VisitOptions
protected activeVisit?: ActiveVisit
protected visitId: VisitId = null
protected page!: Page

public init({
initialPage,
resolveComponent,
swapComponent,
visitOptions,
}: {
initialPage: Page,
resolveComponent: PageResolver,
swapComponent: PageHandler,
visitOptions: VisitOptions,
}): void {
this.page = initialPage
this.resolveComponent = resolveComponent
this.swapComponent = swapComponent
this.visitOptions = visitOptions

if (this.isBackForwardVisit()) {
this.handleBackForwardVisit(this.page)
Expand Down Expand Up @@ -195,28 +199,36 @@ export class Router {
}
}

public visit(href: string|URL, {
method = Method.GET,
data = {},
replace = false,
preserveScroll = false,
preserveState = false,
only = [],
headers = {},
errorBag = '',
forceFormData = false,
onCancelToken = () => {},
onBefore = () => {},
onStart = () => {},
onProgress = () => {},
onFinish = () => {},
onCancel = () => {},
onSuccess = () => {},
onError = () => {},
queryStringArrayFormat = 'brackets',
}: VisitOptions = {}): void {
public visit(href: string|URL, params: VisitParams = {}): void {
const options: Required<VisitParams> = {
method: Method.GET,
data: {},
replace: false,
preserveScroll: false,
preserveState: false,
only: [],
headers: {},
errorBag: '',
forceFormData: false,
queryStringArrayFormat: 'brackets',
onCancelToken: () => {},
onBefore: () => {},
onStart: () => {},
onProgress: () => {},
onFinish: () => {},
onCancel: () => {},
onSuccess: () => {},
onError: () => {},
... params,
}

let url = typeof href === 'string' ? hrefToUrl(href) : href

const prepared = this.visitOptions(options, url) || options

const { method, replace, only, headers, errorBag, forceFormData, queryStringArrayFormat, onCancelToken, onBefore, onStart, onProgress, onFinish, onCancel, onSuccess, onError } = prepared
let { data, preserveScroll, preserveState } = prepared

if ((hasFiles(data) || forceFormData) && !(data instanceof FormData)) {
data = objectToFormData(data)
}
Expand Down Expand Up @@ -417,32 +429,32 @@ export class Router {
}
}

public get(url: URL|string, data: RequestPayload = {}, options: Exclude<VisitOptions, 'method'|'data'> = {}): void {
public get(url: URL|string, data: RequestPayload = {}, options: Exclude<VisitParams, 'method'|'data'> = {}): void {
return this.visit(url, { ...options, method: Method.GET, data })
}

public reload(options: Exclude<VisitOptions, 'preserveScroll'|'preserveState'> = {}): void {
public reload(options: Exclude<VisitParams, 'preserveScroll'|'preserveState'> = {}): void {
return this.visit(window.location.href, { ...options, preserveScroll: true, preserveState: true })
}

public replace(url: URL|string, options: Exclude<VisitOptions, 'replace'> = {}): void {
public replace(url: URL|string, options: Exclude<VisitParams, 'replace'> = {}): void {
console.warn(`Inertia.replace() has been deprecated and will be removed in a future release. Please use Inertia.${options.method ?? 'get'}() instead.`)
return this.visit(url, { preserveState: true, ...options, replace: true })
}

public post(url: URL|string, data: RequestPayload = {}, options: Exclude<VisitOptions, 'method'|'data'> = {}): void {
public post(url: URL|string, data: RequestPayload = {}, options: Exclude<VisitParams, 'method'|'data'> = {}): void {
return this.visit(url, { preserveState: true, ...options, method: Method.POST, data })
}

public put(url: URL|string, data: RequestPayload = {}, options: Exclude<VisitOptions, 'method'|'data'> = {}): void {
public put(url: URL|string, data: RequestPayload = {}, options: Exclude<VisitParams, 'method'|'data'> = {}): void {
return this.visit(url, { preserveState: true, ...options, method: Method.PUT, data })
}

public patch(url: URL|string, data: RequestPayload = {}, options: Exclude<VisitOptions, 'method'|'data'> = {}): void {
public patch(url: URL|string, data: RequestPayload = {}, options: Exclude<VisitParams, 'method'|'data'> = {}): void {
return this.visit(url, { preserveState: true, ...options, method: Method.PATCH, data })
}

public delete(url: URL|string, options: Exclude<VisitOptions, 'method'> = {}): void {
public delete(url: URL|string, options: Exclude<VisitParams, 'method'> = {}): void {
return this.visit(url, { preserveState: true, ...options, method: Method.DELETE })
}

Expand Down
Loading

0 comments on commit 20b7782

Please sign in to comment.