gpt4 book ai didi

How to handle modal close with InertiaJS form onSuccess?(如何使用InertiaJS Form On Success处理模式关闭?)

转载 作者:bug小助手 更新时间:2023-10-28 13:35:21 28 4
gpt4 key购买 nike



Good day everyone. I'm currently working on a Laravel project. I'm using laravel/breeze VueJS with Inertia. Now, with this project, Login is done using bootstrap modal component. Validation and authentication works well the only issue that I'm facing is that, when successful authentication happens, modal should close and it does but backdrop remains.

大家好。我目前正在做拉威尔的一个项目。我正在使用带惯性的LALAVEL/微风VueJS。现在,在这个项目中,登录是使用Bootstrap模式组件完成的。验证和身份验证工作得很好我面临的唯一问题是,当成功的身份验证发生时,modal应该关闭,它确实关闭了,但背景仍然存在。


One thing that I notice is that the form onSuccess does not execute any emit function. I tried using console.log and it does works.

我注意到的一件事是,onSuccess表单不执行任何emit函数。我尝试使用console.log,它确实起作用了。


Please see the code below for reference...

请参考下面的代码以供参考。


Header.vue

Header.vue


<script setup>
import { ref } from 'vue';
import Modal from '@/Components/Modal.vue'

let thisModal = ref(null)

function showModal() {
thisModal.value.show()
}

function closeModal() {
thisModal.value.close()
}
</script>

<template>
<header class="shadow-sm">
<Modal v-if="! $page.props.auth.user" ref="thisModal">
<template #body>
<Login @closeParent="closeModal" @showParent="showModal" />
<Register />
</template>
</Modal>
</header>
</template>

Modal.vue

Modal.vue


<script setup>
import { onMounted, ref } from 'vue'
import { Modal } from 'bootstrap'

defineProps({
title: String
})

let modalEle = ref(null)
let thisModalObj = null

onMounted(() => {
thisModalObj = new Modal(modalEle.value)
})

function _show() {
thisModalObj.show()
}

function _close() {
thisModalObj.hide()
}

defineExpose({ show: _show, close: _close })
</script>

<template>
<div class="modal fade" tabindex="-1" role="dialog" ref="modalEle">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header bg-secondary">
<slot name="header" />
</div>
<div class="modal-body tab-content py-4">
<slot name="body" />
</div>
<slot name="footer" />
</div>
</div>
</div>
</template>

Login.vue (This is where form is located)

Login.vue(这是表单所在的位置)


<script setup>
import { Link, useForm } from '@inertiajs/vue3'
import Checkbox from '@/Components/Checkbox.vue'
import InputError from '@/Components/InputError.vue'
import InputLabel from '@/Components/InputLabel.vue'
import PrimaryButton from '@/Components/PrimaryButton.vue'
import TextInput from '@/Components/TextInput.vue'
import PasswordToggle from '@/Components/PasswordToggle.vue'

defineProps({
canResetPassword: {
type: Boolean,
},
status: {
type: String,
},
})

const form = useForm({
email: '',
password: '',
remember: false,
})

const emit = defineEmits()

const submit = () => {
form.post(route('login'), {
onFinish: () => form.reset('password'),
// onBefore hides the modal
onBefore: () => emit('closeParent'),
// onError shows the modal
onError: () => emit('showParent'),
// Use onSuccess instead
onSuccess: () => emit('closeParent') // <- This should be the most efficient and user friendly
})
}
</script>

<template>
<form @submit.prevent="submit" id="login-tab" class="tab-pane fade show active" autocomplete="off" novalidate>
<div class="mb-3">
<InputLabel for="email" value="Email" />
<TextInput
id="email"
type="text"
name="email"
v-model="form.email"
autofocus
autocomplete="username"
/>
<InputError class="fs-sm" :message="form.errors.email" />
</div>
<div class="mb-3">
<InputLabel for="password" value="Password" />
<PasswordToggle>
<TextInput
id="password"
type="password"
v-model="form.password"
autocomplete="current-password"
/>
</PasswordToggle>
<InputError class="fs-sm" :message="form.errors.password" />
</div>
<div class="mb-3 d-flex flex-wrap justify-content-between">
<div class="form-check mb-2">
<Checkbox id="remember" name="remember" v-model:checked="form.remember" />
<InputLabel for="remember" value="Remember me" />
</div>
<Link v-if="$page.props.app.canResetPassword" class="fs-sm" :href="route('password.request')">
Forgot password?
</Link>
</div>
<PrimaryButton class="btn-shadow d-block w-100" :disabled="form.processing">
<span v-if="form.processing" class="spinner-border spinner-border-sm me-2" role="status" aria-hidden="true"></span>
<span v-else class="me-2"><i class="ci-unlocked"></i></span>
{{ `Sign in` }}
</PrimaryButton>
</form>
</template>

As you can see, I'm sending emit from Login.vue to call close or show from Header.vue. On the current code, modal is hidden when Sign in button is click and will be shown again if an error occurs like validation or invalid account credentials. I want it to only close when authentication is successful but, again, it seems that emit is not being executed using onSuccess. I think the issue lies with the fact that onSuccess is receiving an Inertia response from the controller as shown below:

如您所见,我从Login.vue发送emit,以从Header.vue调用close或show。在当前代码中,当单击“登录”按钮时,模态将被隐藏,如果发生验证或无效帐户凭据等错误,模态将再次显示。我希望它只在身份验证成功时关闭,但是,似乎没有使用onSuccess执行emit。我认为问题在于onSuccess正在从控制器接收Inertia响应,如下所示:


AuthenticatedSessionController.php

AuthenticatedSessionController.php


/**
* Handle an incoming authentication request.
*/
public function store(LoginRequest $request) // : RedirectResponse
{
$request->authenticate();

$request->session()->regenerate();

return redirect()->intended(RouteServiceProvider::HOME);
}

By the way, the modal code here is an answer provided by @OJay on this post here

顺便说一句,这里的模式代码是@Ojay在这里的帖子上提供的答案


更多回答
优秀答案推荐

Been doing a lot of testing and still got no proper or best way to handle this issue. I've decided to avoid using api and stick with Inertia response/redirects. To resolve the modal's backdrop still remains after successful login redirect issue, I decided to manually remove the modal backdrop on modal parent update event.

我做了很多测试,但仍然没有适当或最好的方法来处理这个问题。我决定避免使用API,而坚持使用惯性响应/重定向。为了解决成功登录重定向后模式的背景仍然存在的问题,我决定手动删除模式父更新事件的模式背景。



  1. If login is successful, a redirect response is fired.


    return redirect()->intended(RouteServiceProvider::HOME);




This causes the page to be redirected to home page without properly closing the modal form which leads to modal backdrop covering the whole page.

这会导致页面在没有正确关闭模式表单的情况下被重定向至主页,从而导致模式背景覆盖整个页面。



  1. To resolve this, I added code that checks the body tag for modal classes and entire document for <div class="modal-backdrop fade show"></div> along with a body style attribute of style="margin-bottom: 8px; overflow: hidden; padding-right: 0px;"



  2. Once modal is open, bootstrap updates the body tag class to <body class="handheld-toolbar-enabled modal-open"> along with the style attribute to style="margin-bottom: 8px; overflow: hidden; padding-right: 0px" it then adds a new element <div class="modal-backdrop fade show"></div>



  3. Taking note of these, I came up with a solution that removes and updates these items which is triggered by modal parent's onUpdated event. The code is as follows




<script setup>
import { ref, onUpdated } from 'vue'
// Get the document's body tag
const body = ref(document.body)

// Function to check and update body tag
const checkAndModifyBody = () => {
const modalOpenClass = 'modal-open'
const expectedStyle = 'margin-bottom: 8px;'
const modalBackdropSelector = 'div.modal-backdrop.fade.show'

if (body.value.classList.contains(modalOpenClass)) {
body.value.classList.remove(modalOpenClass)
}

if (body.value.style.cssText !== expectedStyle) {
body.value.style.cssText = 'margin-bottom: 8px;'
}

const modalBackdrop = body.value.querySelector(modalBackdropSelector)
if (modalBackdrop) {
modalBackdrop.remove()
}
}

// Watch for changes and run the checkAndModifyBody function
watch(body, () => {
checkAndModifyBody()
});

// Initial check
onUpdated(() => {
checkAndModifyBody()
})


This is a dirty solution and not very vue-ish way to handle things.

这是一个肮脏的解决方案,也不是很老套的处理方式。


Thank you everyone and if anybody have a better way of doing things please do let me know.

谢谢大家,如果有人有更好的做事方式,请让我知道。


Cheers!

干杯!


更多回答

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com