diff --git a/docs.json b/docs.json index 16c0f2a..b81e6d5 100644 --- a/docs.json +++ b/docs.json @@ -118,6 +118,7 @@ "group": "Data & Props", "pages": [ "v2/data-props/shared-data", + "v2/data-props/flash-data", "v2/data-props/partial-reloads", "v2/data-props/deferred-props", "v2/data-props/merging-props", diff --git a/v2/advanced/events.mdx b/v2/advanced/events.mdx index effc11d..4ded28c 100644 --- a/v2/advanced/events.mdx +++ b/v2/advanced/events.mdx @@ -435,6 +435,48 @@ router.on('success', (event) => { The `success` event is not cancelable. +## Flash + +v2.3.3+ + +The `flash` event fires when [flash data](/v2/data-props/flash-data) is received from the server. This is useful for displaying toast notifications or handling temporary data in a central location. + + + +```js Vue icon="vuejs" +import { router } from '@inertiajs/vue3' + +router.on('flash', (event) => { + if (event.detail.flash.toast) { + showToast(event.detail.flash.toast) + } +}) +``` + +```jsx React icon="react" +import { router } from '@inertiajs/react' + +router.on('flash', (event) => { + if (event.detail.flash.toast) { + showToast(event.detail.flash.toast) + } +}) +``` + +```js Svelte icon="s" +import { router } from '@inertiajs/svelte' + +router.on('flash', (event) => { + if (event.detail.flash.toast) { + showToast(event.detail.flash.toast) + } +}) +``` + + + +The `flash` event is not cancelable. [Partial reloads](/v2/data-props/partial-reloads) will only trigger the event if the flash data has changed. + ## Error The `error` event fires when validation errors are present on "successful" page visits. diff --git a/v2/data-props/flash-data.mdx b/v2/data-props/flash-data.mdx new file mode 100644 index 0000000..642fa4f --- /dev/null +++ b/v2/data-props/flash-data.mdx @@ -0,0 +1,274 @@ +--- +title: Flash Data +--- + +v2.3.3+ + +Sometimes you may wish to send one-time data to your frontend that shouldn't reappear when users navigate through browser history. Unlike regular props, flash data isn't persisted in history state, making it ideal for success messages, newly created IDs, or other temporary values. + +## Flashing Data + +You may flash data using the `Inertia::flash()` method, passing a key and value or an array of key-value pairs. + +```php +public function store(Request $request) +{ + $user = User::create($request->validated()); + + Inertia::flash('message', 'User created successfully!'); + + // Or flash multiple values at once... + Inertia::flash([ + 'message' => 'User created!', + 'newUserId' => $user->id, + ]); + + return back(); +} +``` + +Chaining with `back()` is also supported. + +```php +return Inertia::flash('newUserId', $user->id)->back(); +``` + +You may also chain `flash()` onto `render()`, or vice versa. + +```php +return Inertia::render('Projects/Index', [ + 'projects' => $projects, +])->flash('highlight', $project->id); + +// Or... + +return Inertia::flash('highlight', $project->id) + ->render('Projects/Index', ['projects' => $projects]); +``` + +Flash data is scoped to the current request. The middleware automatically persists it to the session when redirecting. After the flash data is sent to the client, it is cleared and will not appear in subsequent requests. + +## Accessing Flash Data + +Flash data is available on `page.flash`. You may also listen for the global `flash` event or use the `onFlash` callback. + + + +```vue Vue icon="vuejs" + + + +``` + +```jsx React icon="react" +import { usePage } from '@inertiajs/react' + +export default function Layout({ children }) { + const { flash } = usePage() + + return ( + <> + {flash.toast &&
{flash.toast.message}
} + {children} + + ) +} +``` + +```svelte Svelte icon="s" + + +{#if $page.flash.toast} +
{$page.flash.toast.message}
+{/if} +``` + +
+ +## The onFlash Callback + +You may use the `onFlash` callback to handle flash data when making requests. + + + +```js Vue icon="vuejs" +import { router } from '@inertiajs/vue3' + +router.post('/users', data, { + onFlash: ({ newUserId }) => { + form.userId = newUserId + }, +}) +``` + +```js React icon="react" +import { router } from '@inertiajs/react' + +router.post('/users', data, { + onFlash: ({ newUserId }) => { + form.userId = newUserId + }, +}) +``` + +```js Svelte icon="s" +import { router } from '@inertiajs/svelte' + +router.post('/users', data, { + onFlash: ({ newUserId }) => { + form.userId = newUserId + }, +}) +``` + + + +## Global Flash Event + +You may use the global `flash` event to handle flash data in a central location, such as a layout component. For more information on events, see the [events documentation](/v2/advanced/events). + + + +```js Vue icon="vuejs" +import { router } from '@inertiajs/vue3' + +router.on('flash', (event) => { + if (event.detail.flash.toast) { + showToast(event.detail.flash.toast) + } +}) +``` + +```js React icon="react" +import { router } from '@inertiajs/react' + +router.on('flash', (event) => { + if (event.detail.flash.toast) { + showToast(event.detail.flash.toast) + } +}) +``` + +```js Svelte icon="s" +import { router } from '@inertiajs/svelte' + +router.on('flash', (event) => { + if (event.detail.flash.toast) { + showToast(event.detail.flash.toast) + } +}) +``` + + + +Native browser events are also supported. + + + +```js Vue icon="vuejs" +document.addEventListener('inertia:flash', (event) => { + console.log(event.detail.flash) +}) +``` + +```js React icon="react" +document.addEventListener('inertia:flash', (event) => { + console.log(event.detail.flash) +}) +``` + +```js Svelte icon="s" +document.addEventListener('inertia:flash', (event) => { + console.log(event.detail.flash) +}) +``` + + + +The `flash` event is not cancelable. During [partial reloads](/v2/data-props/partial-reloads), it only fires if the flash data has changed. + +## Client-Side Flash + +You may set flash data on the client without a server request using the `router.flash()` method. Values are merged with existing flash data. + + + +```js Vue icon="vuejs" +import { router } from '@inertiajs/vue3' + +router.flash('foo', 'bar') +router.flash({ foo: 'bar' }) +``` + +```js React icon="react" +import { router } from '@inertiajs/react' + +router.flash('foo', 'bar') +router.flash({ foo: 'bar' }) +``` + +```js Svelte icon="s" +import { router } from '@inertiajs/svelte' + +router.flash('foo', 'bar') +router.flash({ foo: 'bar' }) +``` + + + +A callback may also be passed to access the current flash data or replace it entirely. + + + +```js Vue icon="vuejs" +import { router } from '@inertiajs/vue3' + +router.flash((current) => ({ ...current, bar: 'baz' })) +router.flash(() => ({})) +``` + +```js React icon="react" +import { router } from '@inertiajs/react' + +router.flash((current) => ({ ...current, bar: 'baz' })) +router.flash(() => ({})) +``` + +```js Svelte icon="s" +import { router } from '@inertiajs/svelte' + +router.flash((current) => ({ ...current, bar: 'baz' })) +router.flash(() => ({})) +``` + + + +## TypeScript + +You may configure the flash data type globally using TypeScript's declaration merging. + +```ts +// global.d.ts +declare module '@inertiajs/core' { + export interface InertiaConfig { + flashDataType: { + toast?: { + type: 'success' | 'error' + message: string + } + } + } +} +``` + +With this configuration, `page.flash.toast` will be properly typed as `{ type: "success" | "error"; message: string } | undefined`. diff --git a/v2/data-props/shared-data.mdx b/v2/data-props/shared-data.mdx index a44aeb1..9ad6a86 100644 --- a/v2/data-props/shared-data.mdx +++ b/v2/data-props/shared-data.mdx @@ -147,81 +147,6 @@ export default function Layout({ children }) { -## Flash Messages +## Flash Data -Another great use-case for shared data is flash messages. These are messages stored in the session only for the next request. For example, it's common to set a flash message after completing a task and before redirecting to a different page. - -Here's a simple way to implement flash messages in your Inertia applications. First, share the flash message on each request. - -```php -class HandleInertiaRequests extends Middleware -{ - public function share(Request $request) - { - return array_merge(parent::share($request), [ - 'flash' => [ - 'message' => fn () => $request->session()->get('message') - ], - ]); - } -} -``` - -Next, display the flash message in a frontend component, such as the site layout. - - - -```vue Vue icon="vuejs" - -``` - -```jsx React icon="react" -import { usePage } from '@inertiajs/react' - -export default function Layout({ children }) { - const { flash } = usePage().props - - return ( -
-
-
- {flash.message && ( -
{flash.message}
- )} - {children} -
-
-
- ) -} -``` - -```svelte Svelte icon="s" - - -
-
-
- {#if $page.props.flash.message} -
{$page.props.flash.message}
- {/if} - -
- -
-``` - -
+For one-time notifications like toast messages or success alerts, you may use [flash data](/v2/data-props/flash-data). Unlike shared data, flash data is not persisted in the browser's history state, so it won't reappear when navigating through history.