Skip to content

Commit

Permalink
Update props when redirecting back to same modal
Browse files Browse the repository at this point in the history
  • Loading branch information
pascalbaljet committed Oct 29, 2024
1 parent afcb753 commit d2798a9
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 10 deletions.
13 changes: 12 additions & 1 deletion demo-app/resources/js/Pages/EditUser.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ export default function EditUser({ user, roles }) {
role_id: user.role_id,
});

function updateAndRefresh() {
put(`/users/${user.id}?redirect=edit`)
}

const submit = (e) => {
e.preventDefault();
put(`/users/${user.id}`, {
Expand All @@ -38,7 +42,7 @@ export default function EditUser({ user, roles }) {
{({ close, reload, emit }) => (
<>
<div>
<h2 className="text-lg font-medium text-gray-900">Edit User</h2>
<h2 className="text-lg font-medium text-gray-900">Edit User {user.name}</h2>
{message && <p dusk="message" className="text-sm text-gray-500">{message}</p>}
</div>

Expand Down Expand Up @@ -116,6 +120,13 @@ export default function EditUser({ user, roles }) {
>
Cancel
</button>
<button
type="button"
onClick={updateAndRefresh}
className="ml-3 inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
>
Update and refresh
</button>
<button
type="submit"
className="ml-3 inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
Expand Down
11 changes: 9 additions & 2 deletions demo-app/resources/js/Pages/EditUser.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script setup>
import { useForm } from '@inertiajs/vue3';
import { Modal, ModalLink } from '@inertiaui/modal-vue';
import { Modal, ModalLink, useModal } from '@inertiaui/modal-vue';
import { ref } from 'vue';
import ComponentThatUsesModalInstance from './ComponentThatUsesModalInstance.vue';
Expand All @@ -15,6 +15,10 @@ const form = useForm({
role_id: props.user.role_id,
})
function updateAndRefresh() {
form.put(`/users/${props.user.id}?redirect=edit`)
}
const modalRef = ref(null)
const messageRef = ref('')
Expand All @@ -39,7 +43,7 @@ function onMessage(message) {
#default="{ close, reload, emit }"
>
<div class="">
<h2 class="text-lg font-medium text-gray-900">Edit User</h2>
<h2 class="text-lg font-medium text-gray-900">Edit User {{ user.name }}</h2>
<p dusk="message" v-text="messageRef" v-if="messageRef" class="text-sm text-gray-500" />
</div>

Expand Down Expand Up @@ -82,6 +86,9 @@ function onMessage(message) {
<button type="button" @click="close" class="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-gray-600 hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500">
Cancel
</button>
<button type="button" @click.prevent="updateAndRefresh" class="ml-3 inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
Update and refresh
</button>
<button type="submit" class="ml-3 inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
Save
</button>
Expand Down
4 changes: 4 additions & 0 deletions demo-app/routes/web.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@

session()->flash('message', 'User updated successfully!');

if (request()->query('redirect') === 'edit') {
return redirect()->route('users.edit', $user);
}

return back();
})->name('users.update');

Expand Down
36 changes: 36 additions & 0 deletions demo-app/tests/Browser/RedirectToModalTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace Tests\Browser;

use App\Models\User;
use Illuminate\Support\Str;
use PHPUnit\Framework\Attributes\Test;
use Tests\DuskTestCase;

class RedirectToModalTest extends DuskTestCase
{
#[Test]
public function it_can_submit_a_form_and_redirect_back_to_the_same_modal()
{
$this->browse(function (Browser $browser) {
$firstUser = User::orderBy('name')->first();

$browser->visit('/users?navigate=1')
->waitForFirstUser()
->click("@edit-user-{$firstUser->id}")
->waitForTextIn('.im-modal-content', 'Edit User')
->type('name', $newName = Str::random(10))
->press('Update and refresh')
->waitForText('User updated successfully!')
->within('.im-dialog[data-inertiaui-modal-index="0"]', function (Browser $browser) use ($newName) {
$browser->assertSee('Edit User '.$newName);
})
->assertPathIs('/users/'.$firstUser->id.'/edit');

$this->assertDatabaseHas('users', [
'id' => $firstUser->id,
'name' => $newName,
]);
});
}
}
23 changes: 19 additions & 4 deletions react/src/ModalRoot.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createElement, useEffect, useState } from 'react'
import { default as Axios } from 'axios'
import { except, only } from './helpers'
import { router } from '@inertiajs/react'
import { router, usePage } from '@inertiajs/react'
import { mergeDataIntoQueryString } from '@inertiajs/core'
import { createContext, useContext } from 'react'
import ModalRenderer from './ModalRenderer'
Expand Down Expand Up @@ -226,10 +226,14 @@ export const ModalStackProvider = ({ children }) => {
'X-InertiaUI-Modal-Use-Router': 0,
},
}).then((response) => {
Object.assign(this.props, response.data.props)
updateStack((prevStack) => prevStack) // Trigger re-render
this.updateProps(response.data.props)
})
}

updateProps = (props) => {
Object.assign(this.props, props)
updateStack((prevStack) => prevStack) // Trigger re-render
}
}

const pushFromResponseData = (responseData, config = {}, onClose = null, onAfterLeave = null) => {
Expand Down Expand Up @@ -307,6 +311,7 @@ export const ModalStackProvider = ({ children }) => {
}

if (useInertiaRouter) {
newModalOnBase = null
// Pushing the modal to the stack will be handled by the ModalRoot...
return router.visit(url, {
method,
Expand All @@ -333,7 +338,6 @@ export const ModalStackProvider = ({ children }) => {
)

resolve(modal)
newModalOnBase = null
})
},
})
Expand Down Expand Up @@ -494,6 +498,17 @@ export const ModalRoot = ({ children }) => {
return () => Axios.interceptors.request.eject(axiosRequestInterceptor)
}, [])

const $page = usePage()

useEffect(() => {
const newModal = $page.props?._inertiaui_modal
const previousModal = newModalOnBase?.response

if (newModal && previousModal && newModal.component === previousModal.component && newModal.url === previousModal.url) {
context.stack[0].updateProps(newModal.props ?? {})
}
}, [$page.props?._inertiaui_modal])

return (
<>
{children}
Expand Down
15 changes: 13 additions & 2 deletions vue/src/ModalRoot.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script setup>
import { onBeforeMount, onUnmounted, ref } from 'vue'
import { router } from '@inertiajs/vue3'
import { onBeforeMount, onUnmounted, ref, watch } from 'vue'
import { router, usePage } from '@inertiajs/vue3'
import { useModalStack } from './modalStack'
import ModalRenderer from './ModalRenderer.vue'
import { default as Axios } from 'axios'
Expand Down Expand Up @@ -55,6 +55,17 @@ onBeforeMount(() => {
onUnmounted(() => {
Axios.interceptors.request.eject(axiosRequestInterceptor)
})
const $page = usePage()
watch(
() => $page.props?._inertiaui_modal,
(newModal, previousModal) => {
if (newModal && previousModal && newModal.component === previousModal.component && newModal.url === previousModal.url) {
modalStack.stack.value[0].updateProps(newModal.props ?? {})
}
},
)
</script>
<template>
Expand Down
6 changes: 5 additions & 1 deletion vue/src/modalStack.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,13 @@ class Modal {
'X-InertiaUI-Modal-Use-Router': 0,
},
}).then((response) => {
Object.assign(this.props.value, response.data.props)
this.updateProps(response.data.props)
})
}

updateProps = (props) => {
Object.assign(this.props.value, props)
}
}

function registerLocalModal(name, callback) {
Expand Down

0 comments on commit d2798a9

Please sign in to comment.