├── LICENSE.md ├── README.md ├── package.json └── src ├── ComponentModal.vue ├── IsModalable.vue ├── JetstreamModal.vue ├── Modalable.vue ├── ToModal.vue └── index.js /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Protone Media B.V. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # This package is not maintained anymore, but it has a successor: [Inertia Modal](https://inertiaui.com/inertia-modal/docs/introduction?utm_source=github&utm_campaign=inertia-vue-modal-poc) 🚀 2 | 3 | # Inertia Vue Modal POC 4 | 5 | I've copied the default [Laravel Jetstream](https://jetstream.laravel.com/2.x/stacks/inertia.html) modal component for this demo. 6 | 7 | ## Blog post 8 | 9 | [Proof of Concept: Load any route into a modal with Inertia.js using Laravel and Vue.js](https://protone.media/en/blog/proof-of-concept-load-any-route-into-a-modal-with-inertiajs-using-laravel-and-vuejs) 10 | 11 | ## Limitations 12 | 13 | This POC is a very early draft, so these limitations will probably be fixed soon. 14 | 15 | * No support for nested modals (modal in modal) 16 | * Only tested on Vue 2.6 + Laravel 8 17 | * No access to the parent from within the modal 18 | * No way to close the modal from the parent 19 | * It doesn't use browser history navigation 20 | 21 | ## Installation 22 | 23 | ### Client-side installation 24 | 25 | ```bash 26 | npm i @protonemedia/inertia-vue-modal-poc 27 | ``` 28 | 29 | The only dependency for this POC to work is [vue-portal](https://github.com/LinusBorg/portal-vue). 30 | 31 | In your main JavaScript file, register the `Modalable` and `ToModal` components: 32 | 33 | ```javascript 34 | import Vue from "vue"; 35 | import { Modalable, ToModal } from "@protonemedia/inertia-vue-modal-poc" 36 | import PortalVue from "portal-vue"; 37 | 38 | Vue.component("Modalable", Modalable); 39 | Vue.component("ToModal", ToModal); 40 | Vue.use(PortalVue) 41 | ``` 42 | 43 | In your root layout, you need to add the `ComponentModal` as the last component of your template: 44 | 45 | ```vue 46 | 58 | 59 | 68 | ``` 69 | 70 | ### Server-side installation 71 | 72 | In your Laravel application, you only need to add a few lines of code to the `HandleInertiaRequests` middleware. 73 | 74 | 1. Add the `handle` method to the `HandleInertiaRequests` middleware. 75 | 2. Add the `isModal` property to the shared data array. 76 | 77 | ```php 78 | header('X-Inertia-Modal-Redirect-Back')) { 95 | return back(303); 96 | } 97 | 98 | if (Inertia::getShared('isModal')) { 99 | $response->headers->set('X-Inertia-Modal', true); 100 | } 101 | 102 | return $response; 103 | } 104 | 105 | public function share(Request $request) 106 | { 107 | return array_merge(parent::share($request), [ 108 | 'isModal' => (bool) $request->header('X-Inertia-Modal'), 109 | ]); 110 | } 111 | } 112 | ``` 113 | 114 | ## Usage 115 | 116 | Since we added the `ComponentModal` component, the global `$inertia` object now has a `visitInModal` method. This allows you to make an Inertia visit that loads into the modal. 117 | 118 | You can use this method, for example, in the `@click` handler of a button: 119 | 120 | ```vue 121 | 122 | ``` 123 | 124 | Instead of using the method in your template, you can also use it in your script: 125 | 126 | ```vue 127 | 136 | ``` 137 | 138 | ### Update the page you want to load into a modal 139 | 140 | In most cases, the `/user/create` endpoint renders a form that's wrapped into a template, maybe with other components and components to style the form. Here's a simple example of what the `UserCreate.vue` component might look like: 141 | 142 | ```vue 143 | 157 | 158 | 170 | ``` 171 | 172 | To load this form into a modal, we don't want the sidebar, footer, and styling from the `form-panel` component. We want just the `form` itself! 173 | 174 | To accomplish this, you need to do three things: 175 | 176 | 1. Add the `IsModalable` mixin to your component. 177 | 2. Wrap your *whole* component into the `Modalable` component. 178 | 3. Move the `form` to a separate `#toModal` template and replace it with a `ToModal` component. 179 | 180 | ```vue 181 | 203 | 204 | 224 | ``` 225 | 226 | Now when you visit `/user/create`, nothing has changed! You still have your layout and `form-panel` styling. But when you load this component into a modal, it will only render the `form`. 227 | 228 | ### Handling redirects 229 | 230 | By default, redirects are handled as any other Inertia request. For example you're visiting `/user`, you open `/user/create` in a modal, and after a successful submit, you redirect the user to the detail page of the newly created user: 231 | 232 | ```php 233 | public function store(UserStoreRequest $request) 234 | { 235 | $user = User::create(...); 236 | 237 | return redirect()->route('user.show', $user); 238 | } 239 | ``` 240 | 241 | You might not always want to route to the detail page. Luckily, you don't have to update your server-side implementation. 242 | 243 | The `visitInModal` method accepts a second argument that can either a Boolean or a callback. Instead of redirecting the user, the user stays on the same page, and you can manually handle the event with the callback. This callback is executed after a successful request, for example, when the new user is stored in the database. 244 | 245 | ```javascript 246 | this.$inertia.visitInModal('/user/create', (event) => { 247 | // do something 248 | }); 249 | ``` 250 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@protonemedia/inertia-vue-modal-poc", 3 | "version": "0.0.1", 4 | "description": "Proof of concept for loading routes/components into a modal", 5 | "main": "src/index.js", 6 | "author": "Pascal Baljet", 7 | "license": "MIT", 8 | "private": false, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/protonemedia/inertia-vue-modal-poc.git" 12 | } 13 | } -------------------------------------------------------------------------------- /src/ComponentModal.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | -------------------------------------------------------------------------------- /src/IsModalable.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/JetstreamModal.vue: -------------------------------------------------------------------------------- 1 | 37 | 38 | 103 | -------------------------------------------------------------------------------- /src/Modalable.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | -------------------------------------------------------------------------------- /src/ToModal.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | export { default as ComponentModal } from './ComponentModal' 2 | export { default as IsModalable } from './IsModalable' 3 | export { default as JetstreamModal } from './JetstreamModal' 4 | export { default as Modalable } from './Modalable' 5 | export { default as ToModal } from './ToModal' 6 | --------------------------------------------------------------------------------