4343 :error =" currentPageHasErrors && errorPageIndexes.includes(i)"
4444 :title =" page.title"
4545 :value =" getIndex(i)"
46+ @click =" headerCheckPreviousStepValidation(i)"
4647 >
4748 <v-tooltip
4849 v-if =" !mobile && settings.headerTooltips && page?.fields && page?.fields.length > 0"
6667 </template >
6768 </v-stepper-header >
6869
69- <Form
70+ <form
7071 ref =" stepperFormRef"
71- v-slot =" { validate } "
72- :keep-values-on-unmount =" settings ?.keepValuesOnUnmount "
73- :validate-on-mount =" settings ?.validateOnMount "
74- :validation-schema =" validationSchema "
7572 @submit =" onSubmit"
7673 >
7774 <v-stepper-window >
8481 :value =" getIndex(i)"
8582 >
8683 <v-container >
84+
8785 <PageContainer
8886 v-if =" ! page .isSummary "
8987 :key =" ` ${getIndex (i )}-page ` "
114112 :settings =" settings "
115113 :summaryColumns =" settings ?.summaryColumns "
116114 @goToQuestion =" stepperModel = $event "
117- @submit =" onSubmit (modelValue )"
118115 />
116+
119117 </v-container >
120118 </v-stepper-window-item >
121119 </v-stepper-window >
129127 :disabled =" nextButtonDisabled"
130128 :size =" navButtonSize"
131129 :variant =" navButtonVariant"
132- @click =" runValidation(validate, 'next', next)"
130+ @click =" runValidation('next', next)"
133131 />
134132 <v-btn
135133 v-else
139137 :size =" navButtonSize"
140138 type =" submit"
141139 :variant =" navButtonVariant"
140+ @click =" onSubmit"
142141 >Submit</v-btn >
143142 </template >
144143
153152 />
154153 </template >
155154 </v-stepper-actions >
156- </Form >
155+ </form >
157156 </template >
158157 </v-stepper >
159158 </v-container >
165164// import { VStepper } from 'vuetify/components';
166165// import { VStepperVertical } from 'vuetify/labs/VStepperVertical';
167166import { watchDeep } from ' @vueuse/core' ;
168- import { Form } from ' vee-validate' ;
167+ import { useForm } from ' vee-validate' ;
169168import { useDisplay } from ' vuetify' ;
170169import type {
171170 ComputedClasses ,
@@ -268,6 +267,8 @@ watchDeep(modelValue, () => {
268267
269268const stepperModel = ref (1 );
270269
270+ const currentPageIdx = computed (() => stepperModel .value - 1 );
271+
271272
272273const { mobile, sm } = useDisplay ();
273274const transitionComputed: ComputedRef <Props [' transition' ]> = computed (() => stepperProps .transition );
@@ -295,33 +296,24 @@ const nextButtonDisabled = computed(() => {
295296});
296297
297298const prevButtonDisabled = computed (() => {
298- const currentPage = stepperModel .value - 1 ;
299- const { firstNonEditableIndex, lastNonEditableIndex } = useGetFirstAndLastEditableFalse (computedPages .value );
300- // console.log('currentPage', currentPage);
301- // console.log('firstNonEditableIndex', firstNonEditableIndex);
302- // console.log('lastNonEditableIndex', lastNonEditableIndex);
303- // console.log('isSummary', computedPages.value[currentPage]?.isSummary);
299+ const { lastNonEditableIndex } = useGetFirstAndLastEditableFalse (computedPages .value );
304300
305301 // First Page //
306- if (currentPage === 0 ) {
307- // console.log('FIRST PAGE');
302+ if (currentPageIdx .value === 0 ) {
308303 return true ;
309304 }
310305
311306 // Entire Stepper Form is not editable //
312307 if (! stepperFormIsEditable .value ) {
313- // console.log('NOT EDITABLE');
314308 return true ;
315309 }
316310
317311 // If current page has errors disable //
318312 if (currentPageHasErrors .value ) {
319- // console.log('HAS ERRORS');
320313 return true ;
321314 }
322315
323- if (currentPage - 1 === lastNonEditableIndex ) {
324- // console.log('LAST NON EDITABLE');
316+ if (currentPageIdx .value - 1 === lastNonEditableIndex ) {
325317 return true ;
326318 }
327319
@@ -379,9 +371,8 @@ function headerItemEnabled(page: Page): boolean {
379371 const pageIdx = currentPages .findIndex ((p ) => p === page );
380372 const pageEditable = page .editable !== false ;
381373 const pageNotEditable = page .editable === false ;
382- const currentPageIdx = stepperModel .value - 1 ;
383- const currentPageEditable = currentPages [currentPageIdx ]?.editable !== false ;
384- // const currentPageNotEditable = currentPages[currentPageIdx]?.editable === false;
374+ const currentPageEditable = currentPages [currentPageIdx .value ]?.editable !== false ;
375+ // const currentPageNotEditable = currentPages[currentPageIdx.value]?.editable === false;
385376 const lastPageIdx = currentPages .length - 1 ;
386377
387378 const previousPageIdx = pageIdx - 1 ;
@@ -397,7 +388,7 @@ function headerItemEnabled(page: Page): boolean {
397388 // if (debug) {
398389 // console.groupCollapsed('page', page.title);
399390 // console.log('previousPageIdx\t', previousPageIdx);
400- // console.log('currentPageIdx\t', currentPageIdx);
391+ // console.log('currentPageIdx\t', currentPageIdx.value );
401392 // console.log('nextPageIdx\t\t', nextPageIdx);
402393
403394 // console.log('lastPageIdx\t\t', lastPageIdx);
@@ -419,7 +410,7 @@ function headerItemEnabled(page: Page): boolean {
419410
420411 // & Always True //
421412 // Always set current page to editable //
422- if (currentPageIdx === pageIdx ) {
413+ if (currentPageIdx . value === pageIdx ) {
423414 return true ;
424415 }
425416
@@ -474,17 +465,52 @@ const errorPageIndexes: Ref<number[]> = ref<number[]>([]);
474465
475466const fieldsHaveErrors = computed (() => errorPageIndexes .value .includes (stepperModel .value - 1 ));
476467
468+ const $useForm = useForm ({
469+ initialValues: modelValue .value ,
470+ keepValuesOnUnmount: settings .value ?.keepValuesOnUnmount ,
471+ validationSchema: validationSchema .value ,
472+ valueOnMount: settings .value ?.validateOnMount ,
473+ });
474+
475+
477476// ------------------------ Run Validation //
477+ function headerCheckPreviousStepValidation(index : number ): void {
478+ const previousIndex = index === 0 ? 0 : index - 1 ;
479+ const previousPage = computedPages .value [previousIndex ];
480+
481+ if (! previousPage || ! previousPage .fields ) {
482+ return ;
483+ }
484+
485+ previousPage .fields .forEach ((field ) => {
486+ $useForm .validateField (field .name , {}, { name: field .name })
487+ .then ((response : ValidateResult ) => {
488+ const errors = response .errors as unknown as ValidateResult [' errors' ];
489+
490+ if (errors .length ) {
491+ stepperModel .value = previousIndex + 1 ;
492+ currentPageHasErrors .value = true ;
493+
494+ setPageToError (previousIndex , previousPage , ' submit' );
495+ return ;
496+ }
497+
498+ removePageError (previousIndex );
499+ });
500+ });
501+ }
502+
478503function runValidation(
479- validate : () => Promise <ValidateResult >,
480504 source = ' submit' ,
481505 next : () => void = () => { },
482506): void {
483- validate ()
507+ if (! parentForm .value ) {
508+ return ;
509+ }
510+
511+ $useForm .validate ()
484512 .then ((response : ValidateResult ) => {
485513 const errors = response .errors as unknown as ValidateResult [' errors' ];
486-
487-
488514 checkForPageErrors (errors , source , next );
489515 })
490516 .catch ((error : Error ) => {
@@ -507,8 +533,7 @@ function removePageError(pageIndex: number): void {
507533
508534// ------------------------ Check the if the page has errors //
509535function checkForPageErrors(errors : ValidateResult [' errors' ], source : string , next = () => { }): void {
510- const currentPage = stepperModel .value - 1 ;
511- const page = computedPages .value [currentPage ];
536+ const page = computedPages .value [currentPageIdx .value ];
512537
513538 if (! page ) {
514539 return ;
@@ -551,15 +576,15 @@ function setPageToError(pageIndex: number, page?: Page, source = 'submit'): void
551576let debounceTimer: ReturnType <typeof setTimeout >;
552577
553578function onFieldValidate(field : Field , next : () => void ): void {
554- const errors = parentForm . value ?. errors as ValidateResult [' errors' ];
579+ const errors = $useForm . errorBag as ValidateResult [' errors' ];
555580 const shouldAutoPage = (field .autoPage || settings .value .autoPage ? next : null ) as () => void ;
556581
557582 // If autoPage //
558583 if (field ?.autoPage || settings .value ?.autoPage ) {
559584
560585 if (parentForm .value ) {
561586 // First validate the page before proceeding to the next page //
562- ( parentForm . value as { validate : () => Promise < ValidateResult >; }) .validate ()
587+ $useForm .validate ()
563588 .then ((res : ValidateResult ) => {
564589 if (res .valid ) {
565590 // debounce next //
@@ -571,8 +596,7 @@ function onFieldValidate(field: Field, next: () => void): void {
571596 return ;
572597 }
573598
574- const currentPage = stepperModel .value - 1 ;
575- const page = computedPages .value [currentPage ];
599+ const page = computedPages .value [currentPageIdx .value ];
576600 const pageIndex = computedPages .value .findIndex ((p ) => p === page );
577601
578602 setPageToError (pageIndex , page , ' validating' );
@@ -585,14 +609,18 @@ function onFieldValidate(field: Field, next: () => void): void {
585609 return ;
586610 }
587611
588- checkForPageErrors (errors , ' field' , shouldAutoPage );
612+ $useForm .validateField (field .name , {}, { name: field .name })
613+ .then (() => {
614+ checkForPageErrors ($useForm .errorBag .value , ' field' , shouldAutoPage );
615+
616+ });
589617}
590618
591619
592620// -------------------------------------------------- Submit //
593- function onSubmit( values : any ): void {
621+ const onSubmit = $useForm . handleSubmit (( values : any ): void => {
594622 emit (' submit' , values );
595- }
623+ });
596624
597625
598626// ------------------------------------------------ Callbacks //
0 commit comments