Allow and respect action/target in ValidatedForm and ModalDialog

pull/256/head
Candid Dauth 2024-03-05 04:44:39 +01:00
rodzic b211800973
commit 441780beab
3 zmienionych plików z 31 dodań i 9 usunięć

Wyświetl plik

@ -226,13 +226,13 @@
:id="`${id}-open-form`" :id="`${id}-open-form`"
method="get" method="get"
:action="url" :action="url"
@submit="handleSubmit" @submit.prevent="handleSubmit"
ref="openFormRef" ref="openFormRef"
></ValidatedForm> ></ValidatedForm>
<ValidatedForm <ValidatedForm
:id="`${id}-search-form`" :id="`${id}-search-form`"
@submit="$event.waitUntil(search(searchQuery, 0))" @submit.prevent="$event.waitUntil(search(searchQuery, 0))"
class="results" class="results"
></ValidatedForm> ></ValidatedForm>
</template> </template>

Wyświetl plik

@ -20,6 +20,8 @@
okLabel?: string; okLabel?: string;
okVariant?: ThemeColour; okVariant?: ThemeColour;
formValidationError?: string | undefined; formValidationError?: string | undefined;
action?: string;
target?: string;
}>(), { }>(), {
isModified: false, isModified: false,
size: "lg" size: "lg"
@ -34,7 +36,6 @@
const validatedFormRef = ref<InstanceType<typeof ValidatedForm>>(); const validatedFormRef = ref<InstanceType<typeof ValidatedForm>>();
const isSubmitting = computed(() => validatedFormRef.value?.formData.isSubmitting); const isSubmitting = computed(() => validatedFormRef.value?.formData.isSubmitting);
const submitRef = ref<HTMLElement>();
const modalElementRef = ref<InstanceType<typeof AttributePreservingElement>>(); const modalElementRef = ref<InstanceType<typeof AttributePreservingElement>>();
const modalRef = toRef(() => modalElementRef.value?.elementRef); const modalRef = toRef(() => modalElementRef.value?.elementRef);
@ -58,8 +59,13 @@
function handleSubmit(event: CustomSubmitEvent) { function handleSubmit(event: CustomSubmitEvent) {
if (isCloseButton.value) { if (isCloseButton.value) {
event.preventDefault();
modal.hide(); modal.hide();
} else { } else {
if (!props.action) {
event.preventDefault();
}
emit("submit", event); emit("submit", event);
} }
} }
@ -87,6 +93,8 @@
<div class="modal-dialog modal-dialog-scrollable"> <div class="modal-dialog modal-dialog-scrollable">
<ValidatedForm <ValidatedForm
class="modal-content" class="modal-content"
:action="props.action"
:target="props.target"
@submit="handleSubmit" @submit="handleSubmit"
ref="validatedFormRef" ref="validatedFormRef"
:noValidate="isCloseButton" :noValidate="isCloseButton"
@ -124,7 +132,6 @@
class="btn btn-primary" class="btn btn-primary"
:class="props.okVariant && `btn-${props.okVariant}`" :class="props.okVariant && `btn-${props.okVariant}`"
:disabled="isSubmitting || props.isBusy" :disabled="isSubmitting || props.isBusy"
ref="submitRef"
> >
<div v-if="isSubmitting" class="spinner-border spinner-border-sm"></div> <div v-if="isSubmitting" class="spinner-border spinner-border-sm"></div>
{{props.okLabel ?? (isCloseButton ? 'Close' : 'Save')}} {{props.okLabel ?? (isCloseButton ? 'Close' : 'Save')}}

Wyświetl plik

@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import { type Ref, onScopeDispose, reactive, readonly, ref, watchEffect, toRef } from "vue"; import { type Ref, onScopeDispose, reactive, readonly, ref, watchEffect, toRef } from "vue";
import { type ExtendableEventMixin, extendableEventMixin } from "../../../utils/utils"; import { type ExtendableEventMixin, extendableEventMixin, useDomEventListener } from "../../../utils/utils";
import { useToasts } from "../toasts/toasts.vue"; import { useToasts } from "../toasts/toasts.vue";
export interface ValidatedFormData { export interface ValidatedFormData {
@ -13,6 +13,7 @@
} }
export interface CustomSubmitEvent extends ExtendableEventMixin { export interface CustomSubmitEvent extends ExtendableEventMixin {
preventDefault(): void;
} }
const allForms = reactive(new Map<Ref<HTMLFormElement | undefined>, ValidatedFormData>()); const allForms = reactive(new Map<Ref<HTMLFormElement | undefined>, ValidatedFormData>());
@ -48,9 +49,19 @@
} }
} }
const event = { ...extendableEventMixin }; let prevented = false;
const event = {
...extendableEventMixin,
preventDefault() {
prevented = true;
}
};
onSubmit(event); onSubmit(event);
await event._awaitPromises(); await event._awaitPromises();
if (!prevented) {
formRef.value?.submit();
}
} finally { } finally {
data.isSubmitting = false; data.isSubmitting = false;
} }
@ -77,6 +88,11 @@
data.isValidating = [...isValidating.values()].some((v) => v); data.isValidating = [...isValidating.values()].some((v) => v);
}); });
useDomEventListener(formRef, "submit", (e) => {
e.preventDefault();
data.submit();
});
allForms.set(formRef, data); allForms.set(formRef, data);
onScopeDispose(() => { onScopeDispose(() => {
@ -120,11 +136,10 @@
<template> <template>
<form <form
@submit.prevent="formData.submit()"
novalidate novalidate
ref="formRef" ref="formRef"
:action="props.action" :action="props.action ?? 'javascript:'"
:target="props.target ?? 'javascript:'" :target="props.target"
:class="{ 'fm-was-validated': formData.isTouched }" :class="{ 'fm-was-validated': formData.isTouched }"
> >
<slot :formData="formData"/> <slot :formData="formData"/>