Skip to content

Commit 2c51ba2

Browse files
[DEV] Fixing all fields with new form validation the way it should have been
1 parent 6c8bd98 commit 2c51ba2

File tree

26 files changed

+611
-1312
lines changed

26 files changed

+611
-1312
lines changed

src/plugin/VStepperForm.vue

Lines changed: 69 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,12 @@
5656
</template>
5757
</v-stepper-header>
5858

59-
<!-- <Form
60-
ref="formFieldRef"
59+
<Form
60+
ref="stepperFormRef"
61+
v-slot="{ validate }"
6162
:validation-schema="validateSchema"
62-
@submit.prevent="onSubmit"
63-
> -->
64-
<form @submit.prevent="onSubmit">
63+
@submit="onSubmit"
64+
>
6565
<v-stepper-window>
6666
<v-stepper-window-item
6767
v-for="page, i in pages"
@@ -78,9 +78,7 @@
7878
:index="getIndex(i)"
7979
:page="page"
8080
:settings="settings"
81-
:validateSchema="validateSchema"
82-
@next="validatePage('page')"
83-
@validate="onValidate($event, next)"
81+
@validate="onFieldValidate($event, next)"
8482
>
8583
<!-- ========================= Pass Slots -->
8684
<template
@@ -101,7 +99,7 @@
10199
:settings="settings"
102100
:summary-columns="summaryColumns"
103101
@goToQuestion="stepperModel = $event"
104-
@submit="onSubmit"
102+
@submit="onSubmit(modelValue)"
105103
/>
106104
</v-container>
107105
</v-stepper-window-item>
@@ -114,8 +112,9 @@
114112
:color="settings.color"
115113
:disabled="nextButtonDisabled"
116114
:size="navButtonSize"
117-
@click="validatePage('page')"
115+
@click="runValidation(validate, 'next', next)"
118116
/>
117+
<!-- TODO: This will change to use v-else when done -->
119118
<v-btn
120119
:color="settings.color"
121120
:disabled="fieldsHaveErrors && errorPageIndexes.includes(stepperModel - 1)"
@@ -137,8 +136,7 @@
137136
<v-col>
138137
</v-col>
139138
</v-row>
140-
</form>
141-
<!-- </Form> -->
139+
</Form>
142140
</template>
143141
</v-stepper>
144142
</v-container>
@@ -148,11 +146,13 @@
148146
</template>
149147

150148
<script setup lang="ts">
149+
// TODO: Conditionals needs to update the validation //
151150
// import { VStepper } from 'vuetify/components';
152151
// import { VStepperVertical } from 'vuetify/labs/VStepperVertical';
153152
import { AllProps } from './utils/props';
154153
import { useDisplay } from 'vuetify';
155-
// import { Form } from 'vee-validate';
154+
import { Form } from 'vee-validate';
155+
import type { PrivateFormContext } from 'vee-validate';
156156
import type {
157157
ComputedClasses,
158158
EmitValidateEventPayload,
@@ -168,18 +168,12 @@ import {
168168
useStepperContainerClasses,
169169
} from './composables/classes';
170170
import componentEmits from './utils/emits';
171-
import { TriggerValidationBus } from './utils/globals';
172171
import { globalOptions } from './';
173172
import PageContainer from './components/shared/PageContainer.vue';
174173
import PageReviewContainer from './components/shared/PageReviewContainer.vue';
175174
import { useMergeProps } from './composables/helpers';
176-
import {
177-
useEventBus,
178-
watchDeep,
179-
} from '@vueuse/core';
180-
import {
181-
useGetValidationSchema,
182-
} from './composables/validation';
175+
import { watchDeep } from '@vueuse/core';
176+
import { useGetValidationSchema } from './composables/validation';
183177
184178
185179
const attrs = useAttrs();
@@ -190,7 +184,6 @@ const injectedOptions = inject(globalOptions, {});
190184
191185
// -------------------------------------------------- Props //
192186
const props = withDefaults(defineProps<Props>(), AllProps);
193-
194187
const stepperProps = reactive<Settings>(useMergeProps(attrs, injectedOptions, props));
195188
const { direction, title, width } = toRefs(props);
196189
const pages = reactive<Page[]>(props.pages);
@@ -246,11 +239,6 @@ Object.values(pages).forEach((p: Page) => {
246239
// -------------------------------------------------- Mounted //
247240
onMounted(() => {
248241
whenCallback();
249-
250-
// useSetupValidation({
251-
// fields: allFieldsArray.value,
252-
// });
253-
254242
summaryColumnErrorCheck();
255243
});
256244
@@ -267,6 +255,10 @@ const stepperModel = ref(1);
267255
268256
const { sm } = useDisplay();
269257
const transition = computed<Props['transition']>(() => stepperProps.transition);
258+
const parentForm = useTemplateRef<PrivateFormContext>('stepperFormRef');
259+
260+
provide('parentForm', parentForm);
261+
270262
271263
272264
// -------------------------------------------------- Stepper Action //
@@ -287,17 +279,9 @@ const canReviewPreviousButtonDisabled = computed<boolean>(() => {
287279
return stepperModel.value === pages.length && !props.canReview;
288280
});
289281
290-
// ------------------------- Next Page //
291-
function nextPage(next: () => void): void {
292-
// console.log('nextPage');
293-
294-
next();
295-
}
296282
297283
// ------------------------- Previous Page //
298284
function previousPage(prev: () => void): void {
299-
// console.log('previousPage');
300-
301285
if (canReviewPreviousButtonDisabled.value) {
302286
return;
303287
}
@@ -325,173 +309,92 @@ function headerItemDisabled(page: Page): boolean {
325309
326310
327311
// & ------------------------------------------------ Validation //
328-
const validateSchema = useGetValidationSchema(allFieldsArray.value as SchemaField[]);
312+
const validateSchema = props.schema ?? useGetValidationSchema(allFieldsArray.value as SchemaField[]);
329313
const fieldsHaveErrors = ref(false);
330314
const currentPageHasErrors = ref(false);
331315
const errorPageIndexes = ref<number[]>([]);
332-
let triggerValidationBus: unknown | any;
333-
334-
onMounted(() => {
335-
triggerValidationBus = useEventBus<string>(TriggerValidationBus);
336-
});
337316
317+
// ------------------------ Run Validation //
318+
function runValidation(
319+
validate: () => Promise<ValidateResult>,
320+
source = 'submit',
321+
next: () => void = () => { },
322+
): void {
323+
validate()
324+
.then((response: ValidateResult) => {
325+
checkForPageErrors(response.errors, source, next);
326+
});
327+
}
338328
339-
// ------------------------ Set Page to Errors //
340-
function setPageToError(pageIndex: EmitValidateEventPayload['pageIndex'], page?: Page, isSubmit = false): void {
341-
currentPageHasErrors.value = true;
329+
// ------------------------ Remove error from Page //
330+
function removePageError(pageIndex: number): void {
331+
if (errorPageIndexes.value.includes(pageIndex)) {
332+
const errPageIdx = errorPageIndexes.value.indexOf(pageIndex);
342333
343-
if (page) {
344-
// eslint-disable-next-line no-param-reassign
345-
page.error = true;
334+
if (errPageIdx > -1) {
335+
errorPageIndexes.value.splice(errPageIdx, 1);
336+
}
346337
}
347338
348-
if (!errorPageIndexes.value.includes(pageIndex) && !isSubmit) {
349-
errorPageIndexes.value.push(pageIndex);
350-
}
339+
currentPageHasErrors.value = false;
351340
}
352341
353-
// ------------------------ Validation callback from fields //
354-
function onValidate(payload: EmitValidateEventPayload, event: () => void) {
355-
console.log('onValidate', payload);
356-
const page = pages[payload.pageIndex];
342+
// ------------------------ Check the if the page has errors //
343+
function checkForPageErrors(errors: ValidateResult['errors'], source: string, next = () => { }): void {
344+
const currentPage = stepperModel.value - 1;
357345
358-
// console.log('page', page);
346+
const page = pages[currentPage];
359347
360348
if (!page) {
361349
return;
362350
}
363351
352+
const pageIndex = pages.findIndex((p) => p === page);
353+
const pageFields = page.fields;
354+
const hasErrorInField = Object.keys(errors).some(errorKey => pageFields.some(field => field.name === errorKey));
364355
365-
// ! ------------------------------------------------------------ THIS IS STILL WRONG //
366-
// const currentFieldIndex = page.fields.findIndex((f) => f.name === payload.fieldName);
367-
// const hiddenFieldsLength = page.fields.filter((f) => f.type !== 'hidden').length;
368-
// const pageFieldsLengthZeroBased = page.fields.length - 1;
369-
// const pageFieldsLengthWithoutHidden = page.fields.length - hiddenFieldsLength;
370-
371-
372-
// // Do not continue if field is not the last field //
373-
// // ! THIS NEEDS MORE WORK //
374-
// if (currentFieldIndex !== pageFieldsLengthZeroBased && pageFieldsLengthZeroBased !== pageFieldsLengthWithoutHidden) {
375-
// return;
376-
// }
356+
if (hasErrorInField) {
357+
currentPageHasErrors.value = true;
377358
378-
// Get fields of the current page
379-
const currentPageFields = page.fields;
380-
381-
// Filter out hidden fields (fields without a 'type' or with 'type' set to 'hidden' are considered hidden)
382-
const visibleFields = currentPageFields.filter((f) => f.type !== undefined && f.type !== 'hidden');
383-
384-
// Get the index of the current field in the full list of fields on the current page
385-
// const currentFieldIndex = currentPageFields.findIndex((f) => f.name === payload.fieldName);
386-
387-
// Get the last index of visible fields on the current page
388-
const lastVisibleFieldIndex = visibleFields.length - 1;
389-
390-
// Find the index of the current field in the visible fields array
391-
const currentVisibleFieldIndex = visibleFields.findIndex((f) => f.name === payload.fieldName);
392-
393-
// Only continue if the current field is the last visible field on the page
394-
if (currentVisibleFieldIndex !== lastVisibleFieldIndex) {
359+
setPageToError(pageIndex, page, source);
395360
return;
396361
}
397362
398-
// ! ------------------------------------------------------------ THIS IS STILL WRONG //
399-
400-
if (payload.action === 'page') {
401-
page.error = payload.error === true;
402-
403-
if (page.error) {
404-
setPageToError(payload.pageIndex, page);
405-
return;
406-
}
363+
removePageError(pageIndex);
407364
408-
currentPageHasErrors.value = false;
365+
if (next && !lastPage.value && source !== 'submit') {
366+
next();
409367
}
368+
}
410369
411-
let fieldsErrors = false;
412-
413-
// Check all page fields for Submit //
414-
if (payload.action === 'submit') {
415-
Object.values(pages).forEach((p: Page) => {
416-
const page = p;
417-
418-
// Reset the page error for clean slate to check for errors //
419-
page.error = false;
420-
421-
Object.values(page.fields).forEach((field: Field) => {
422-
if (field.type !== 'hidden' && field.type != null && field.error === true) {
423-
fieldsErrors = true;
424-
page.error = true;
425-
}
426-
});
427-
428-
if (fieldsErrors) {
429-
setPageToError(payload.pageIndex, page, true);
430-
}
431-
});
432-
433-
if (fieldsErrors) {
434-
return;
435-
}
436-
}
437-
else {
438-
Object.values(page.fields).forEach((field: Field) => {
439-
if (field.type !== 'hidden' && field.type != null && field.error === true) {
440-
fieldsErrors = true;
441-
}
442-
// if (field.type !== 'hidden' && field.type != null && (field.error === true || !Object.prototype.hasOwnProperty.call(field, 'error'))) {
443-
// fieldsErrors = true;
444-
// }
445-
});
446-
}
447-
448-
if (fieldsErrors) {
449-
setPageToError(payload.pageIndex);
450-
return;
451-
}
452-
453-
// Remove error from Page //
454-
const errPageIdx = errorPageIndexes.value.indexOf(payload.pageIndex);
455-
456-
if (errPageIdx > -1) {
457-
errorPageIndexes.value.splice(errPageIdx, 1);
458-
}
459370
460-
currentPageHasErrors.value = false;
371+
// ------------------------ Set Page to Errors //
372+
function setPageToError(pageIndex: EmitValidateEventPayload['pageIndex'], page?: Page, source = 'submit'): void {
373+
currentPageHasErrors.value = true;
461374
462-
// Form is complete and without errors. Submit form. //
463-
if (payload.action === 'submit' && lastPage.value) {
464-
submitForm();
465-
return;
375+
if (page && source === 'submit') {
376+
// eslint-disable-next-line no-param-reassign
377+
page.error = true;
466378
}
467379
468-
// Continue to the next Page //
469-
if (payload.nextPage && stepperModel.value === payload.pageIndex + 1) {
470-
nextPage(event);
380+
if (!errorPageIndexes.value.includes(pageIndex)) {
381+
errorPageIndexes.value.push(pageIndex);
471382
}
472383
}
473384
474-
// ------------------------ Page validation triggering //
475-
function validatePage(action = 'page'): void {
476-
// console.log('validatePage');
385+
// ------------------------ Validation callback from fields //
386+
function onFieldValidate(field: Field, next: () => void): void {
387+
const errors = parentForm.value?.errors as unknown as ValidateResult['errors'];
388+
const shouldAutoPage = (field.autoPage ? next : null) as () => void;
477389
478-
triggerValidationBus.emit({
479-
action,
480-
pageIndex: stepperModel.value,
481-
});
390+
checkForPageErrors(errors, 'field', shouldAutoPage);
482391
}
483392
484393
485394
// -------------------------------------------------- Submit //
486-
function onSubmit(val): void {
487-
console.log('onSubmit', val);
488-
489-
validatePage('submit');
490-
}
491-
492-
function submitForm(): void {
493-
console.log('%c%s', 'color: #00ff00; font-weight: bold;', '======================== SUBMIT FORM');
494-
emit('submit');
395+
function onSubmit(values: any): void {
396+
console.log('%c%s', 'color: #00ff00; font-weight: bold;', '======================== onSubmit SUBMIT FORM \n', values);
397+
emit('submit', values);
495398
}
496399
497400
@@ -510,8 +413,6 @@ function whenCallback(): void {
510413
511414
if (indexPage?.fields[fieldIdx]) {
512415
indexPage.fields[fieldIdx].type = enabledField ? originalPages[pageIdx].fields[fieldIdx].type : 'hidden';
513-
514-
// TODO: Update validation? //
515416
}
516417
}
517418
});

0 commit comments

Comments
 (0)