├── 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 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
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 |
144 |
145 |
146 |
147 |
148 |
154 |
155 |
156 |
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 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
200 |
201 |
202 |
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 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/src/IsModalable.vue:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/JetstreamModal.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |