Replies: 10 comments 1 reply
-
I just had an interesting chat with @ninjaparade about this, and we came up with the concept of "partials". Imagine this server-side code: class OrganizationsController
{
public function index()
{
return Inertia::render('Organizations/Index', [
'organizations' => Organization::all(),
]);
}
public function create()
{
return Inertia::partial('Modals/CreateOrganization', [
'countries' => Countries::all(),
])->defaultPage(fn () => $this->index());
}
} So, when making an Inertia request to This design would allow you to display the It would be awesome if the return Inertia::partial('Modals/CreateOrganization', [
'countries' => Countries::all(),
])->defaultPage(fn () => Inertia::render('Organizations/Index', [
'organizations' => Organization::all(),
])); This whole idea makes me want rename the return Inertia::page('Organizations/Index', [
'organizations' => Organization::all(),
]); |
Beta Was this translation helpful? Give feedback.
-
Hmm feels a bit weird, i’d expect url’s to be tied to pages not partials. A modal or slideover, to me, is a state a page could be in. Having a modal or slideover being shown via an # seems more intuitive: organizations/#create. And how would state be handled in this case? Lets say you have a create modal, fill in half of the data and then dismiss it. What happens when you bring back the modal? As you’re calling it with a url I suppose the partial resets? That having said, it would be neat if you can “inject” and populate modals and slideovers like this. Also, no more need to register/place them manually within other components I guess. Just having some trouble getting used to it/wrap my head around it I guess. |
Beta Was this translation helpful? Give feedback.
-
It sounds almost like the Instagram/Reddit navigation style (which seems to be supported in Next.js - see this video), with some differences. The style I'm referencing would be something like a "partial visit":
Users can then interact with that page inside the modal directly or hit "esc" to close the modal and return to the previous page (which was already rendered behind the modal, but the URL changes back). While the "partial visit" is active, if the page is refreshed, server-side routing would pick it up and render that page, but this time as a fullpage (no modals). Assuming that the page also has a persistent layout, these could be ignored on partial visits, but used on regular visits (this way we don't render the navigation inside the modal, for example). What you're describing is a bit different, though. The page would always render inside a modal no matter what. So if the user refreshes the page, you would use the "default page" to render behind the modal. |
Beta Was this translation helpful? Give feedback.
-
this sounds actually a good example. Instagram have done this some time ago and i always tho it was a great ideia, the only "problem" i see here is the fact that the modal itself should also be able to render itself alone in minimal view, wich in my opinion is bad UX i believe @reinink ideia is great, because whenever you call a certain endpoint/url you always have the modal/slideover available and visible, wich is really nice for crud operations such as update/create/delete confirmations and such, while still being able to close it and have its "underlying" page with the content fresh. And from my understanding still benefit from lazy evaluation. I see a really good path here to be honest :) keep up the good work! |
Beta Was this translation helpful? Give feedback.
-
I think that is the important part. I like the idea of partials, but do not expect that Inertia renders the component inside the frontend framework. For me, that's way out of scope of Inertia and also conflicts with the different frontend frameworks supported. Currently I am building an app that is already using most of the curtently existing techniques of Inertia to render modals. Most of the current backend implementation can be seen in this issue. In the Vue frontend the main component just contains a modal component with a <template>
...
<v-edit-client-modal v-show="actions.isEditingClient" :client="client" :errors="errors" @close="closeModals" />
...
</template>
<script>
export default {
props: {
errors: Object,
clients: Array,
client: Object,
actions: {
type: Object,
default: () => ({
isEditingClient: false,
}),
},
},
methods: {
editClient(slug) {
this.$inertia.visit(route('clients.edit', { slug }), {
preserveScroll: true,
preserveState: true,
only: ['client', 'actions'],
});
},
closeModals() {
this.$inertia.visit(route('clients.index'), {
preserveScroll: true,
preserveState: true,
only: ['actions'],
});
},
},
</script>
Within the modal component, there's an this.$inertia.patch(route('clients.update', { slug }), data, {
preserveScroll: true,
preserveState: true,
only: ['clients', 'actions'],
}); The only thing I am struggling with is I have to call return Inertia::render('clients', [
'actions' => [
'isEditingClient' => false,
],
]); Returns: {
"component": "clients",
"props": {
"actions": { "isEditingClient": false }
},
"url": "/clients/client-slug",
"version": "..."
} The url should be that of the main component: That's mostly that what @druc solves in his appraoch by introducing the renderUrl method to the inertia-laravel adapter. For me everything is working, all modals have their own url and history/back works. Just using the lazy loading and some custom directives to control the modals from the backend. |
Beta Was this translation helpful? Give feedback.
-
I would like to ask about some cases that i'm solving by doing some flash hacking. At the moment i've kinda hacked this together and wrote about it here: https://medium.com/@mykolas.mankevicius/laravel-inertia-js-vue-modal-madness-f32d3ba4b4f0 Let me know if you need me to expand on anything. Great work |
Beta Was this translation helpful? Give feedback.
-
To avoid all this v-if and extra control variables, I am just using a entire separated page with its own controller/route as described on #44 (comment) |
Beta Was this translation helpful? Give feedback.
-
My primary use case for Inertia-rendered modals are inline create or edit forms. We often build dropdowns with a "create" button next to them which opens up a modal with a form to create a new model without leaving the current page. The reason why this is difficult without Inertia are data dependencies. Consider the following relationship: a user belongs to an organization, an organisation belongs to a location. The controller method to render the user form would look like this: public function edit(User $user)
{
return inertia('Users/Edit', [
'user' => $user,
'organizations' => Organization::all(),
]);
} The edit user form has a dropdown to select an organization. The admin may also create an organization with a create button nest tot the dropdown. This button displays a modal with an organization form. The organization form has a dropdown to select a location. That means the user form would need to know this to populate that dropdown. public function edit(User $user)
{
return inertia('Users/Edit', [
'user' => $user,
'organizations' => Organization::all(),
'locations' => Location::all(),
]);
} This doesn't scale well at all. We're often sending down locations for nothing, and more importantly it's hard to reason about the data dependencies of the user edit view, since the locations aren't explicitly part of the form. De Would partials be treated like a single element or a stack? Could you render a partial over a partial? Or would a new partial replace the current one? |
Beta Was this translation helpful? Give feedback.
-
@sebastiandedeyne you may want to have a look at how i've done this. As i'm not sure the new partial will solve the nested modals thing. |
Beta Was this translation helpful? Give feedback.
-
My use case for Inertia partials is a table which can be filtered, searched, paginated. This works perfectly in Inertia on pages with one table, but pages with multiple tables are a challenge. @reinink Could you say where partials are on your roadmap? |
Beta Was this translation helpful? Give feedback.
-
Inertia is designed such that each page has it's own URL, server-side controller, and client-side page component. This setup matches how you build classic server-side rendered applications.
This pattern, however, doesn't apply well to modals, slideovers, drawers and the like very well, since they are almost pages inside other pages. Sometimes they even have their own URLs, and therefore history state. Currently this behaviour is not possible with Inertia.
That said, you can absolutely still use modals within an Inertia app. Often in these situations it's best to simply submit any modal forms via xhr/fetch directly, instead of making an Inertia request.
I am creating this issue, since we get asked about modals a lot, and I'd like to research if there are ways that we can improve Inertia to make modals easier to work with...or if nothing else, write some good documentation around best practices here.
Related issues: #44, #119, #100, #103, #106, #122
Beta Was this translation helpful? Give feedback.
All reactions