56
56
</template >
57
57
</v-stepper-header >
58
58
59
- <!-- <Form
60
- ref="formFieldRef"
59
+ <Form
60
+ ref =" stepperFormRef"
61
+ v-slot =" { validate }"
61
62
:validation-schema =" validateSchema"
62
- @submit.prevent="onSubmit"
63
- > -->
64
- <form @submit.prevent =" onSubmit" >
63
+ @submit =" onSubmit"
64
+ >
65
65
<v-stepper-window >
66
66
<v-stepper-window-item
67
67
v-for =" page, i in pages"
78
78
:index =" getIndex(i)"
79
79
:page =" page"
80
80
:settings =" settings"
81
- :validateSchema =" validateSchema"
82
- @next =" validatePage('page')"
83
- @validate =" onValidate($event, next)"
81
+ @validate =" onFieldValidate($event, next)"
84
82
>
85
83
<!-- ========================= Pass Slots -->
86
84
<template
101
99
:settings =" settings"
102
100
:summary-columns =" summaryColumns"
103
101
@goToQuestion =" stepperModel = $event"
104
- @submit =" onSubmit"
102
+ @submit =" onSubmit(modelValue) "
105
103
/>
106
104
</v-container >
107
105
</v-stepper-window-item >
114
112
:color =" settings.color"
115
113
:disabled =" nextButtonDisabled"
116
114
:size =" navButtonSize"
117
- @click =" validatePage('page' )"
115
+ @click =" runValidation(validate, 'next', next )"
118
116
/>
117
+ <!-- TODO: This will change to use v-else when done -->
119
118
<v-btn
120
119
:color =" settings.color"
121
120
:disabled =" fieldsHaveErrors && errorPageIndexes.includes(stepperModel - 1)"
137
136
<v-col >
138
137
</v-col >
139
138
</v-row >
140
- </form >
141
- <!-- </Form> -->
139
+ </Form >
142
140
</template >
143
141
</v-stepper >
144
142
</v-container >
148
146
</template >
149
147
150
148
<script setup lang="ts">
149
+ // TODO: Conditionals needs to update the validation //
151
150
// import { VStepper } from 'vuetify/components';
152
151
// import { VStepperVertical } from 'vuetify/labs/VStepperVertical';
153
152
import { AllProps } from ' ./utils/props' ;
154
153
import { useDisplay } from ' vuetify' ;
155
- // import { Form } from 'vee-validate';
154
+ import { Form } from ' vee-validate' ;
155
+ import type { PrivateFormContext } from ' vee-validate' ;
156
156
import type {
157
157
ComputedClasses ,
158
158
EmitValidateEventPayload ,
@@ -168,18 +168,12 @@ import {
168
168
useStepperContainerClasses ,
169
169
} from ' ./composables/classes' ;
170
170
import componentEmits from ' ./utils/emits' ;
171
- import { TriggerValidationBus } from ' ./utils/globals' ;
172
171
import { globalOptions } from ' ./' ;
173
172
import PageContainer from ' ./components/shared/PageContainer.vue' ;
174
173
import PageReviewContainer from ' ./components/shared/PageReviewContainer.vue' ;
175
174
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' ;
183
177
184
178
185
179
const attrs = useAttrs ();
@@ -190,7 +184,6 @@ const injectedOptions = inject(globalOptions, {});
190
184
191
185
// -------------------------------------------------- Props //
192
186
const props = withDefaults (defineProps <Props >(), AllProps );
193
-
194
187
const stepperProps = reactive <Settings >(useMergeProps (attrs , injectedOptions , props ));
195
188
const { direction, title, width } = toRefs (props );
196
189
const pages = reactive <Page []>(props .pages );
@@ -246,11 +239,6 @@ Object.values(pages).forEach((p: Page) => {
246
239
// -------------------------------------------------- Mounted //
247
240
onMounted (() => {
248
241
whenCallback ();
249
-
250
- // useSetupValidation({
251
- // fields: allFieldsArray.value,
252
- // });
253
-
254
242
summaryColumnErrorCheck ();
255
243
});
256
244
@@ -267,6 +255,10 @@ const stepperModel = ref(1);
267
255
268
256
const { sm } = useDisplay ();
269
257
const transition = computed <Props [' transition' ]>(() => stepperProps .transition );
258
+ const parentForm = useTemplateRef <PrivateFormContext >(' stepperFormRef' );
259
+
260
+ provide (' parentForm' , parentForm );
261
+
270
262
271
263
272
264
// -------------------------------------------------- Stepper Action //
@@ -287,17 +279,9 @@ const canReviewPreviousButtonDisabled = computed<boolean>(() => {
287
279
return stepperModel .value === pages .length && ! props .canReview ;
288
280
});
289
281
290
- // ------------------------- Next Page //
291
- function nextPage(next : () => void ): void {
292
- // console.log('nextPage');
293
-
294
- next ();
295
- }
296
282
297
283
// ------------------------- Previous Page //
298
284
function previousPage(prev : () => void ): void {
299
- // console.log('previousPage');
300
-
301
285
if (canReviewPreviousButtonDisabled .value ) {
302
286
return ;
303
287
}
@@ -325,173 +309,92 @@ function headerItemDisabled(page: Page): boolean {
325
309
326
310
327
311
// & ------------------------------------------------ Validation //
328
- const validateSchema = useGetValidationSchema (allFieldsArray .value as SchemaField []);
312
+ const validateSchema = props . schema ?? useGetValidationSchema (allFieldsArray .value as SchemaField []);
329
313
const fieldsHaveErrors = ref (false );
330
314
const currentPageHasErrors = ref (false );
331
315
const errorPageIndexes = ref <number []>([]);
332
- let triggerValidationBus: unknown | any ;
333
-
334
- onMounted (() => {
335
- triggerValidationBus = useEventBus <string >(TriggerValidationBus );
336
- });
337
316
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
+ }
338
328
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 );
342
333
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
+ }
346
337
}
347
338
348
- if (! errorPageIndexes .value .includes (pageIndex ) && ! isSubmit ) {
349
- errorPageIndexes .value .push (pageIndex );
350
- }
339
+ currentPageHasErrors .value = false ;
351
340
}
352
341
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 ;
357
345
358
- // console.log(' page', page) ;
346
+ const page = pages [ currentPage ] ;
359
347
360
348
if (! page ) {
361
349
return ;
362
350
}
363
351
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 ));
364
355
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 ;
377
358
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 );
395
360
return ;
396
361
}
397
362
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 );
407
364
408
- currentPageHasErrors .value = false ;
365
+ if (next && ! lastPage .value && source !== ' submit' ) {
366
+ next ();
409
367
}
368
+ }
410
369
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
- }
459
370
460
- currentPageHasErrors .value = false ;
371
+ // ------------------------ Set Page to Errors //
372
+ function setPageToError(pageIndex : EmitValidateEventPayload [' pageIndex' ], page ? : Page , source = ' submit' ): void {
373
+ currentPageHasErrors .value = true ;
461
374
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 ;
466
378
}
467
379
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 );
471
382
}
472
383
}
473
384
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 ;
477
389
478
- triggerValidationBus .emit ({
479
- action ,
480
- pageIndex: stepperModel .value ,
481
- });
390
+ checkForPageErrors (errors , ' field' , shouldAutoPage );
482
391
}
483
392
484
393
485
394
// -------------------------------------------------- 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 );
495
398
}
496
399
497
400
@@ -510,8 +413,6 @@ function whenCallback(): void {
510
413
511
414
if (indexPage ?.fields [fieldIdx ]) {
512
415
indexPage .fields [fieldIdx ].type = enabledField ? originalPages [pageIdx ].fields [fieldIdx ].type : ' hidden' ;
513
-
514
- // TODO: Update validation? //
515
416
}
516
417
}
517
418
});
0 commit comments