Have a look at this. It's updated regularly and seems popular
Package to use InertiaJS to open a page in a modal window
Hello,
Who has tested this package ? It seems to be very interesting to load a route in a modal window.
https://github.com/protonemedia/inertia-vue-modal-poc
If anyone can share its experience about this package ;).
Thanks.
V
@Sinnbeck Oh thank you it looks interesting, I will test it. Furthermore it is headless and it doesn't seem to need InertiaJS SSR (whereas the other one --- inertia-vue-modal-poc --- needs SSR).
@vincent15000 and I trust the author. He makes great stuff for laravel
@Sinnbeck I'm right now testing the package. I come back to tell you something ;).
@Sinnbeck I have installed the package, the route works fine, but the modal window doesn't display.
I use the el-dialog component (from the Element Plus framework).
I try to open my modal formby clicking on the Edit button in the states datatable.
Inertia.visit(route('states.edit', stateId))
My controller.
public function edit(State $state)
{
$states = State:all();
return Inertia::modal('States/Form')->with(compact('state'))->baseRoute('states.index', $states);
return $state;
}
And the template of my modal form.
<el-dialog
:title="title"
v-modal="dialogVisible"
width="50%"
@open="loadData()"
:close-on-click-modal="false"
destroy-on-close>
<el-form
ref="form"
:model="state"
label-position="right"
label-width="160px">
<el-form-item label="Nom">
<el-input v-model="state.name"></el-input>
</el-form-item>
<el-form-item label="Couleur">
<el-color-picker v-model="state.color" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="close()">Annuler</el-button>
<el-button type="primary" @click="save()">Enregistrer</el-button>
</span>
</template>
</el-dialog>
Even if (for the moment) it doesn't work / display, I think that this package doesn't allow to have a real modal window. By reading the documentation, I understand that the page loads the modal window and the background isn't real and is only a kind of image of the datatable or any back page. But perhaps I am wrong.
@Sinnbeck Is there another way to load an InertiaJS page on a modal page ?
@vincent15000 sadly I have never used the package as I use react instead of vue
Personally I just use regular modals so I don't have any experience with other solutions
@vincent15000 You need to wrap your form inside a Modal from the package.
import { Modal } from 'momentum-modal'I don't know if this is too late, but the package has a sort of a bug, that for some reason you can't access data as a prop, but you can access it differently, same as you would do with inertia-shared data, usePage().props.value.modal.props.{name of the prop}
I think the plugin is very interesting but, it is a bit of a mess. For example, has with() to use, and in the provider, it is not returned, therefore not even used. So the issue is on the part of laravel implementation and not vue. Although for what is worth it so far is the best solution for this type of operation. I mean besides working with API-s.
@mnplus I have decided to use simple axios queries to save / update / destroy my models, so I don't use InertiaJS for my modal views.
Here's simple implementation using InertiaJs shared data and Headless UI component
In your HandleInertiaRequests
public function share(Request $request): array
{
return array_merge(parent::share($request), [
'flash' => [
'title' => fn() => $request->session()->get('title'),
'description' => fn() => $request->session()->get('description'),
],
]);
}
Then place your modal in your Layout file (eg AppLayout.vue)
<template>
<div class="fixed inset-0 flex items-center justify-center">
<button
type="button"
@click="openModal"
class="rounded-md bg-black/20 px-4 py-2 text-sm font-medium text-white hover:bg-black/30 focus:outline-none focus-visible:ring-2 focus-visible:ring-white/75"
>
Open dialog
</button>
</div>
<TransitionRoot appear :show="isOpen" as="template">
<Dialog as="div" @close="closeModal" class="relative z-10">
<TransitionChild
as="template"
enter="duration-300 ease-out"
enter-from="opacity-0"
enter-to="opacity-100"
leave="duration-200 ease-in"
leave-from="opacity-100"
leave-to="opacity-0"
>
<div class="fixed inset-0 bg-black/25" />
</TransitionChild>
<div class="fixed inset-0 overflow-y-auto">
<div
class="flex min-h-full items-center justify-center p-4 text-center"
>
<TransitionChild
as="template"
enter="duration-300 ease-out"
enter-from="opacity-0 scale-95"
enter-to="opacity-100 scale-100"
leave="duration-200 ease-in"
leave-from="opacity-100 scale-100"
leave-to="opacity-0 scale-95"
>
<DialogPanel
class="w-full max-w-md transform overflow-hidden rounded-2xl bg-white p-6 text-left align-middle shadow-xl transition-all"
>
<DialogTitle
as="h3"
class="text-lg font-medium leading-6 text-gray-900"
>
{{ title }}
</DialogTitle>
<div class="mt-2">
<p class="text-sm text-gray-500">
{{ description }}
</p>
</div>
<div class="mt-4">
<button
type="button"
class="inline-flex justify-center rounded-md border border-transparent bg-blue-100 px-4 py-2 text-sm font-medium text-blue-900 hover:bg-blue-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"
@click="closeModal"
>
Got it, thanks!
</button>
</div>
</DialogPanel>
</TransitionChild>
</div>
</div>
</Dialog>
</TransitionRoot>
</template>
<script setup>
import { ref } from "vue";
import {
TransitionRoot,
TransitionChild,
Dialog,
DialogPanel,
DialogTitle,
} from "@headlessui/vue";
defineProps({
title: String,
description: String,
});
const isOpen = ref(true);
function closeModal() {
isOpen.value = false;
}
function openModal() {
isOpen.value = true;
}
</script>
and in your controller
{
if ($role->name === 'Super Admin') {
session()->flash('flash.banner', 'The Super Admin" role cannot be deleted');
session()->flash('flash.bannerStyle', 'error');
return redirect()->back()->with('modal', 'The "Super Admin" role cannot be deleted.')->with('description', 'Super Admin role cannot be deleted.');
}
$role->delete();
return redirect()->back()->with('status', 'Role deleted successfully');
}
Please or to participate in this conversation.