#8725 - submit_form_onClick #1564

Merged
jsegarra merged 25 commits from 8725_submit_form_onClick into dev 2025-04-08 12:58:52 +00:00
6 changed files with 46 additions and 19 deletions

View File

@ -13,13 +13,12 @@ import VnConfirm from './ui/VnConfirm.vue';
import { tMobile } from 'src/composables/tMobile'; import { tMobile } from 'src/composables/tMobile';
import { useArrayData } from 'src/composables/useArrayData'; import { useArrayData } from 'src/composables/useArrayData';
import { getDifferences, getUpdatedValues } from 'src/filters'; import { getDifferences, getUpdatedValues } from 'src/filters';
const { push } = useRouter(); const { push } = useRouter();
const quasar = useQuasar(); const quasar = useQuasar();
const state = useState(); const state = useState();
const stateStore = useStateStore(); const stateStore = useStateStore();
const { t } = useI18n(); const { t } = useI18n();
const { validate } = useValidator(); const { validate, validations } = useValidator();
const { notify } = useNotify(); const { notify } = useNotify();
const route = useRoute(); const route = useRoute();
const myForm = ref(null); const myForm = ref(null);
@ -119,7 +118,7 @@ const defaultButtons = computed(() => ({
color: 'primary', color: 'primary',
icon: 'save', icon: 'save',
label: 'globals.save', label: 'globals.save',
click: async () => await save(), click: async (evt) => submitForm(evt),
type: 'submit', type: 'submit',
}, },
reset: { reset: {
@ -132,6 +131,13 @@ const defaultButtons = computed(() => ({
...$props.defaultButtons, ...$props.defaultButtons,
})); }));
const submitForm = async (evt) => {
const isFormValid = await myForm.value.validate();
if (isFormValid) {
await save(evt);
}
};
onMounted(async () => { onMounted(async () => {
nextTick(() => (componentIsRendered.value = true)); nextTick(() => (componentIsRendered.value = true));
@ -227,10 +233,9 @@ async function save() {
const method = $props.urlCreate ? 'post' : 'patch'; const method = $props.urlCreate ? 'post' : 'patch';
const url = const url =
$props.urlCreate || $props.urlUpdate || $props.url || arrayData.store.url; $props.urlCreate || $props.urlUpdate || $props.url || arrayData.store.url;
let response; const response = await Promise.resolve(
$props.saveFn ? $props.saveFn(body) : axios[method](url, body),
if ($props.saveFn) response = await $props.saveFn(body); );
else response = await axios[method](url, body);
if ($props.urlCreate) notify('globals.dataCreated', 'positive'); if ($props.urlCreate) notify('globals.dataCreated', 'positive');
@ -307,11 +312,13 @@ async function onKeyup(evt) {
selectionStart = selectionEnd = selectionStart + 1; selectionStart = selectionEnd = selectionStart + 1;
return; return;
} }
await save(); await myForm.value.submit(evt);
} }
} }
defineExpose({ defineExpose({
submitForm,
myForm,
save, save,
isLoading, isLoading,
hasChanges, hasChanges,
@ -325,7 +332,7 @@ defineExpose({
<QForm <QForm
ref="myForm" ref="myForm"
v-if="formData" v-if="formData"
@submit.prevent @submit.prevent="save"
@keyup.prevent="onKeyup" @keyup.prevent="onKeyup"
Outdated
Review

Este prevent se quita?

Este prevent se quita?

Lo he corregido

Lo he corregido
@reset="reset" @reset="reset"
class="q-pa-md" class="q-pa-md"
@ -339,6 +346,7 @@ defineExpose({
name="form" name="form"
:data="formData" :data="formData"
:validate="validate" :validate="validate"
:validations="validations()"
Review

Aqui se esta llamando

Aqui se esta llamando
Review

validations devuelve una función

validations devuelve una función
:filter="filter" :filter="filter"
/> />
<SkeletonForm v-else /> <SkeletonForm v-else />

View File

@ -41,9 +41,12 @@ const onDataSaved = async (formData, requestResponse) => {
emit('onDataSaved', formData, requestResponse); emit('onDataSaved', formData, requestResponse);
}; };
const onClick = async (saveAndContinue) => { const onClick = async (saveAndContinue = showSaveAndContinueBtn) => {
await formModelRef.value.myForm.validate(true);
isSaveAndContinue.value = saveAndContinue; isSaveAndContinue.value = saveAndContinue;
await formModelRef.value.save(); if (formModelRef.value) {
await formModelRef.value.submitForm();
}
}; };
defineExpose({ defineExpose({
@ -59,16 +62,23 @@ defineExpose({
ref="formModelRef" ref="formModelRef"
:observe-form-changes="false" :observe-form-changes="false"
:default-actions="false" :default-actions="false"
@submit="onClick"
v-bind="$attrs" v-bind="$attrs"
@on-data-saved="onDataSaved" @on-data-saved="onDataSaved"
:prevent-submit="false"
> >
<template #form="{ data, validate }"> <template #form="{ data, validate, validations }">
<span ref="closeButton" class="close-icon" v-close-popup> <span ref="closeButton" class="close-icon" v-close-popup>
<QIcon name="close" size="sm" /> <QIcon name="close" size="sm" />
</span> </span>
<h1 class="title">{{ title }}</h1> <h1 class="title">{{ title }}</h1>
<p>{{ subtitle }}</p> <p>{{ subtitle }}</p>
<slot name="form-inputs" :data="data" :validate="validate" /> <slot
name="form-inputs"
:data="data"
:validate="validate"
:validations="validations"
/>
<div class="q-mt-lg row justify-end"> <div class="q-mt-lg row justify-end">
<QBtn <QBtn
:label="t('globals.cancel')" :label="t('globals.cancel')"
@ -87,12 +97,13 @@ defineExpose({
:flat="showSaveAndContinueBtn" :flat="showSaveAndContinueBtn"
:label="t('globals.save')" :label="t('globals.save')"
:title="t('globals.save')" :title="t('globals.save')"
@click="onClick(false)" :type="!showSaveAndContinueBtn ? 'submit' : 'button'"
Review

Si funciona igual, veo mas simple usar 2 @click q 4 ternarios

Si funciona igual, veo mas simple usar 2 @click q 4 ternarios
Review

No entiendo.
No funcionan igual. Uno al pulsar, esconde el modal y el continue, limpia el formulario y se mantiene a la vista
Son 2 botones diferentes y tienen condiciones diferentes

No entiendo. No funcionan igual. Uno al pulsar, esconde el modal y el continue, limpia el formulario y se mantiene a la vista Son 2 botones diferentes y tienen condiciones diferentes
color="primary" color="primary"
class="q-ml-sm" class="q-ml-sm"
:disabled="isLoading" :disabled="isLoading"
:loading="isLoading" :loading="isLoading"
data-cy="FormModelPopup_save" data-cy="FormModelPopup_save"
@click="showSaveAndContinueBtn ? onClick(false) : null"
z-max z-max
/> />
<QBtn <QBtn
@ -100,12 +111,13 @@ defineExpose({
:label="t('globals.isSaveAndContinue')" :label="t('globals.isSaveAndContinue')"
:title="t('globals.isSaveAndContinue')" :title="t('globals.isSaveAndContinue')"
color="primary" color="primary"
:type="showSaveAndContinueBtn ? 'submit' : 'button'"
class="q-ml-sm" class="q-ml-sm"
:disabled="isLoading" :disabled="isLoading"
:loading="isLoading" :loading="isLoading"
data-cy="FormModelPopup_isSaveAndContinue" data-cy="FormModelPopup_isSaveAndContinue"
@click="showSaveAndContinueBtn ? onClick(true) : null"
z-max z-max
@click="onClick(true)"
/> />
</div> </div>
</template> </template>

View File

@ -1044,7 +1044,7 @@ const rowCtrlClickFunction = computed(() => {
:model="$attrs['data-key'] + 'Create'" :model="$attrs['data-key'] + 'Create'"
@on-data-saved="(_, res) => createForm.onDataSaved(res)" @on-data-saved="(_, res) => createForm.onDataSaved(res)"
> >
<template #form-inputs="{ data }"> <template #form-inputs="{ data, validations }">
<slot name="alter-create" :data="data"> <slot name="alter-create" :data="data">
<div :style="createComplement?.containerStyle"> <div :style="createComplement?.containerStyle">
<div <div
@ -1062,6 +1062,7 @@ const rowCtrlClickFunction = computed(() => {
:key="column.name" :key="column.name"
:name="`column-create-${column.name}`" :name="`column-create-${column.name}`"
:data="data" :data="data"
:validations="validations"
:column-name="column.name" :column-name="column.name"
:label="column.label" :label="column.label"
> >

View File

@ -79,7 +79,7 @@ async function acceptPropagate({ isEqualizated }) {
observe-form-changes observe-form-changes
@on-data-saved="checkEtChanges" @on-data-saved="checkEtChanges"
> >
<template #form="{ data, validate }"> <template #form="{ data, validate, validations }">
<VnRow> <VnRow>
<VnInput <VnInput
:label="t('Social name')" :label="t('Social name')"
@ -112,6 +112,7 @@ async function acceptPropagate({ isEqualizated }) {
v-model="data.sageTaxTypeFk" v-model="data.sageTaxTypeFk"
data-cy="sageTaxTypeFk" data-cy="sageTaxTypeFk"
:required="data.isTaxDataChecked" :required="data.isTaxDataChecked"
:rules="[(val) => validations.required(data.isTaxDataChecked, val)]"
/> />
<VnSelect <VnSelect
:label="t('Sage transaction type')" :label="t('Sage transaction type')"
@ -122,6 +123,9 @@ async function acceptPropagate({ isEqualizated }) {
data-cy="sageTransactionTypeFk" data-cy="sageTransactionTypeFk"
v-model="data.sageTransactionTypeFk" v-model="data.sageTransactionTypeFk"
:required="data.isTaxDataChecked" :required="data.isTaxDataChecked"
:rules="[
(val) => validations.required(data.sageTransactionTypeFk, val),
]"
> >
<template #option="scope"> <template #option="scope">
<QItem v-bind="scope.itemProps"> <QItem v-bind="scope.itemProps">

View File

@ -787,7 +787,7 @@ onMounted(() => {
<span data-cy="footer-amount">{{ footer?.amount }} / </span> <span data-cy="footer-amount">{{ footer?.amount }} / </span>
<span style="color: var(--q-positive)">{{ footer?.checkedAmount }}</span> <span style="color: var(--q-positive)">{{ footer?.checkedAmount }}</span>
</template> </template>
<template #column-create-itemFk="{ data }"> <template #column-create-itemFk="{ data, validations }">
<VnSelect <VnSelect
url="Items/search" url="Items/search"
v-model="data.itemFk" v-model="data.itemFk"
@ -801,7 +801,8 @@ onMounted(() => {
await setBuyUltimate(value, data); await setBuyUltimate(value, data);
} }
" "
:required="true" required
:rules="[(val) => validations.required(true, val)]"
data-cy="itemFk-create-popup" data-cy="itemFk-create-popup"
sort-by="nickname DESC" sort-by="nickname DESC"
> >

View File

@ -19,6 +19,7 @@ describe('Item summary', () => {
cy.get('.q-menu > .q-list > :nth-child(1) > .q-item__section').click(); cy.get('.q-menu > .q-list > :nth-child(1) > .q-item__section').click();
cy.dataCy('regularizeStockInput').type('10'); cy.dataCy('regularizeStockInput').type('10');
cy.dataCy('Warehouse_select').type('Warehouse One{enter}'); cy.dataCy('Warehouse_select').type('Warehouse One{enter}');
cy.dataCy('FormModelPopup_save').click();
cy.checkNotification('Data created'); cy.checkNotification('Data created');
}); });
}); });