Skip to content

Commit 09ae8db

Browse files
[DEV] Working on validation
1 parent 6898eb9 commit 09ae8db

File tree

8 files changed

+346
-152
lines changed

8 files changed

+346
-152
lines changed

src/plugin/VStepperForm.vue

Lines changed: 175 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,17 @@
1212
</h2>
1313
</v-col>
1414
</v-row>
15+
<!-- <v-row>
16+
<v-col>
17+
stepperMode: {{ stepperModel }}
18+
<br />
19+
currentPageHasErrors: {{ currentPageHasErrors }}
20+
<br />
21+
errorPageIndexes: {{ errorPageIndexes }}
22+
<br />
23+
triggerValidation: {{ triggerValidation }}
24+
</v-col>
25+
</v-row> -->
1526
</v-container>
1627

1728
<v-container
@@ -28,18 +39,18 @@
2839
<v-stepper-header>
2940
<template
3041
v-for="(page, i) in pages"
31-
:key="`${i}-step`"
42+
:key="`${getIndex(i)}-step`"
3243
>
3344
<v-stepper-item
3445
:color="settings.color"
3546
:disabled="headerItemDisabled(page)"
3647
:edit-icon="page.isReview ? '$complete' : settings.editIcon"
3748
:editable="page.editable"
3849
elevation="0"
50+
:error="page.error"
3951
:title="page.title"
4052
:value="getIndex(i)"
4153
></v-stepper-item>
42-
4354
<v-divider
4455
v-if="getIndex(i) !== Object.keys(pages).length"
4556
:key="getIndex(i)"
@@ -51,21 +62,23 @@
5162
<v-stepper-window>
5263
<v-stepper-window-item
5364
v-for="page, i in pages"
54-
:key="`${i}-content`"
65+
:key="`${getIndex(i)}-content`"
5566
:reverse-transition="transition"
5667
:transition="transition"
5768
:value="getIndex(i)"
5869
>
5970
<v-container>
6071
<PageContainer
6172
v-if="!page.isReview"
73+
:key="`${getIndex(i)}-page`"
6274
v-model="modelValue"
6375
:index="getIndex(i)"
6476
:page="page"
6577
:settings="settings"
78+
:triggerValidation="triggerValidation"
6679
:validateSchema="validateSchema"
6780
@next="validatePage(next)"
68-
@validate="onSubmit"
81+
@validate="onValidate"
6982
/>
7083
<PageReviewContainer
7184
v-else
@@ -84,11 +97,18 @@
8497
<v-stepper-actions v-if="!settings.hideActions">
8598
<template #next>
8699
<v-btn
100+
v-if="!lastPage"
87101
:color="settings.color"
88-
:disabled="((stepperActionsDisabled === 'next' || settings.disabled) as boolean)"
102+
:disabled="nextButtonDisabled"
89103
:size="navButtonSize"
90104
@click="validatePage(next)"
91105
/>
106+
<v-btn
107+
:color="settings.color"
108+
:disabled="fieldsHaveErrors && errorPageIndexes.includes(stepperModel - 1)"
109+
:size="navButtonSize"
110+
type="submit"
111+
>Submit</v-btn>
92112
</template>
93113

94114
<template #prev>
@@ -102,7 +122,6 @@
102122

103123
<v-row>
104124
<v-col>
105-
<v-btn type="submit">Submit</v-btn>
106125
</v-col>
107126
</v-row>
108127
</form>
@@ -151,8 +170,9 @@ const injectedOptions = inject(globalOptions, {});
151170
const props = withDefaults(defineProps<Props>(), AllProps);
152171
153172
const stepperProps = reactive<Settings>(useMergeProps(attrs, injectedOptions, props));
154-
const { direction, pages, title, width } = toRefs(props);
155-
const originalPages = JSON.parse(JSON.stringify(pages.value));
173+
const { direction, title, width } = toRefs(props);
174+
const pages = reactive(props.pages);
175+
const originalPages = JSON.parse(JSON.stringify(pages));
156176
157177
const settings = ref<Settings>({
158178
altLabels: stepperProps.altLabels,
@@ -190,58 +210,14 @@ const settings = ref<Settings>({
190210
console.log('settings.value', settings.value);
191211
192212
193-
// const { handleSubmit } = useForm({
194-
// validationSchema: toTypedSchema(
195-
// yupObject({
196-
// }),
197-
// ),
198-
// });
199-
200-
// const onSubmit = handleSubmit(item => {
201-
// console.log('onSubmit handleSubmit', item);
202-
// });
203-
204213
const allFieldsArray = ref<Field[]>([]);
205214
206-
Object.values(pages.value).forEach((p: Page) => {
215+
Object.values(pages).forEach((p: Page) => {
207216
Object.values(p.fields).forEach((field: Field) => {
208217
allFieldsArray.value.push(field as Field);
209218
});
210219
});
211220
212-
const validateSchema = useGetValidationSchema(allFieldsArray.value);
213-
console.log('validateSchema', validateSchema);
214-
215-
// const initialValues = {};
216-
// allFieldsArray.value.forEach(item => {
217-
// initialValues[item.name] = item.label || "";
218-
// });
219-
220-
// const yepSchema = allFieldsArray.value.reduce(useCreateYupSchema, { validationType: 'required', validations: allFieldsArray.value });
221-
// console.log('yepSchema', yepSchema);
222-
// const validateSchema = yupObject().shape(yepSchema);
223-
// console.log('validateSchema', validateSchema);
224-
225-
// const foo = useCreateYupSchema(allFieldsArray.value, {});
226-
227-
// console.log(foo);
228-
229-
function onSubmit() {
230-
console.log('onSubmit');
231-
// useValidation({
232-
// fields: allFieldsArray.value,
233-
// });
234-
}
235-
236-
237-
// function validateField(field: Field) {
238-
// console.log('validateField', field);
239-
// console.log('allFieldsArray', allFieldsArray.value);
240-
// useValidation({
241-
// fields: allFieldsArray.value,
242-
// });
243-
// }
244-
245221
246222
// const StepperComponent = markRaw(props.direction === 'vertical' ? VStepperVertical : VStepper);
247223
// console.log('StepperComponent', StepperComponent);
@@ -256,9 +232,6 @@ onMounted(() => {
256232
// });
257233
258234
summaryColumnErrorCheck();
259-
260-
261-
262235
});
263236
264237
@@ -272,7 +245,7 @@ watchDeep(modelValue, () => {
272245
const stepperModel = ref(1);
273246
274247
watch(stepperModel, () => {
275-
if (stepperModel.value === pages.value.length) {
248+
if (stepperModel.value === pages.length) {
276249
formCompleted.value = true;
277250
}
278251
});
@@ -287,18 +260,18 @@ const stepperActionsDisabled = computed(() => {
287260
return stepperModel.value === 1 ? 'prev' : stepperModel.value === Object.keys(props.pages).length ? 'next' : undefined;
288261
});
289262
290-
// TODO: Make this disabled if the previous page is not editable //
291-
const canReviewPreviousButtonDisabled = computed(() => {
292-
// console.log('canReviewPreviousButtonDisabled');
263+
const nextButtonDisabled = computed(() => {
264+
const foo = ((stepperActionsDisabled.value === 'next' || settings.value.disabled) as boolean);
293265
294-
return stepperModel.value === pages.value.length && !props.canReview;
295-
});
266+
const currentPageHasError = errorPageIndexes.value.includes(stepperModel.value - 1);
296267
297-
// const previousButtonDisabled = computed(() => {
298-
// return stepperModel.value === 1;
299-
// });
268+
return currentPageHasError || foo;
269+
});
300270
301-
// console.log('previousButtonDisabled', previousButtonDisabled.value);
271+
// TODO: Make this disabled if the previous page is not editable //
272+
const canReviewPreviousButtonDisabled = computed(() => {
273+
return stepperModel.value === pages.length && !props.canReview;
274+
});
302275
303276
function nextPage(next: () => void): void {
304277
console.log('nextPage', next);
@@ -316,6 +289,10 @@ function previousPage(prev: () => void): void {
316289
prev();
317290
}
318291
292+
const lastPage = computed(() => {
293+
return stepperModel.value === Object.keys(pages).length;
294+
});
295+
319296
320297
// TODO: This needs some more work and add a setting to not allow users to jump ahead in the questions //
321298
function headerItemDisabled(page: Page): boolean {
@@ -331,36 +308,159 @@ function headerItemDisabled(page: Page): boolean {
331308
}
332309
333310
334-
// ------------------------------------------------ Callback & Validation //
311+
// & ------------------------------------------------ Validation //
312+
const validateSchema = useGetValidationSchema(allFieldsArray.value);
313+
const triggerValidation = ref(false);
314+
const fieldsHaveErrors = ref(false);
315+
316+
console.log('validateSchema', validateSchema);
317+
318+
319+
320+
// function validateButtonDisabled() {
321+
// const foo = JSON.parse(JSON.stringify(pages));
322+
// console.log('foo', foo);
323+
// fieldsHaveErrors.value = Object.values(pages).some((page: Page) => Object.values(page.fields).some((field: Field) => field.error));
324+
325+
// console.log('fieldsHaveErrors', fieldsHaveErrors.value);
335326
327+
// }
328+
329+
330+
// TODO: This needs to be fixed //
331+
const currentPageHasErrors = ref(false);
332+
const errorPageIndexes = ref<number[]>([]);
336333
337-
// const pagesValidation = ref((pages.value)
338-
// .map((_, i) => ({ page: i + 1, valid: false })));
334+
function checkForPageErrors() {
335+
errorPageIndexes.value = [];
336+
337+
Object.values(pages).forEach((p: Page, i: number) => {
338+
const errorField = Object.values(p.fields).find((field: Field) => field.error);
339+
340+
if (errorField) {
341+
// eslint-disable-next-line no-param-reassign
342+
p.error = true;
343+
errorPageIndexes.value.push(i);
344+
return;
345+
}
346+
347+
// eslint-disable-next-line no-param-reassign
348+
p.error = false;
349+
});
350+
351+
// Reset the error //
352+
const stepperPage = pages[stepperModel.value - 1];
353+
354+
if (stepperPage) {
355+
stepperPage.error = false;
356+
}
357+
358+
currentPageHasErrors.value = errorPageIndexes.value.includes(stepperModel.value - 1);
359+
}
360+
361+
362+
// TODO: Figure out why this triggers twice for each field on the page //
363+
function onValidate(val) {
364+
console.group('onValidate');
365+
console.log(val);
366+
367+
const { errors, fieldName } = val;
368+
let fieldHasErrors = false;
369+
370+
if (errors) {
371+
fieldHasErrors = errors[fieldName] || false;
372+
}
373+
374+
const fieldPageIdx = Object.values(pages).findIndex((page: Page) => Object.values(page.fields).find((f: Field) => f.name === fieldName));
375+
const page = pages[fieldPageIdx];
376+
377+
console.log('page', page);
378+
379+
if (!page) {
380+
console.groupEnd();
381+
382+
return;
383+
}
384+
385+
const field = page.fields.find((f: Field) => f.name === val.fieldName);
386+
387+
console.log('field', field);
388+
389+
if (!field) {
390+
console.groupEnd();
391+
return;
392+
}
393+
394+
console.log('fieldHasErrors', fieldHasErrors);
395+
396+
field.error = fieldHasErrors ? true : false;
397+
page.error = field.error;
398+
currentPageHasErrors.value = field.error;
399+
fieldsHaveErrors.value = field.error;
400+
401+
console.log('pages', pages);
402+
403+
console.log(currentPageHasErrors.value);
404+
405+
checkForPageErrors();
406+
407+
// Resets so it can be triggered again //
408+
triggerValidation.value = false;
409+
410+
console.groupEnd();
411+
412+
// validateButtonDisabled();
413+
414+
}
415+
416+
417+
418+
function onSubmit(val) {
419+
triggerValidation.value = true;
420+
checkForPageErrors();
421+
422+
console.log('onSubmit', val);
423+
if (fieldsHaveErrors.value) {
424+
return;
425+
}
426+
// useValidation({
427+
// fields: allFieldsArray.value,
428+
// });
429+
}
339430
340-
// console.log('pagesValidation', pagesValidation.value);
341431
342432
function validatePage(event: () => void): void {
343433
console.log('validatePage', event);
434+
triggerValidation.value = true;
344435
345-
console.log('stepperModel', stepperModel.value);
346-
nextPage(event);
347-
}
436+
setTimeout(() => {
437+
// Resets so it can be triggered again //
438+
triggerValidation.value = false;
348439
440+
if (currentPageHasErrors.value) {
441+
return;
442+
}
349443
444+
nextPage(event);
445+
}, 250);
446+
447+
// nextPage(event);
448+
}
350449
351450
451+
// ------------------------------------------------ Callbacks //
352452
function callbacks() {
353453
whenCallback();
354454
}
355455
356456
357457
// ------------------------ Conditional "when" callback //
358458
function whenCallback() {
359-
Object.values(pages.value).forEach((page: Page, pageIdx: number) => {
459+
Object.values(pages).forEach((page: Page, pageIdx: number) => {
360460
Object.values(page.fields as Field[]).forEach((field: Field, fieldIdx) => {
361461
if (field.when) {
362462
const enabledField: boolean = field.when(modelValue.value);
363-
const indexPage = pages.value[pageIdx];
463+
const indexPage = pages[pageIdx];
364464
365465
if (indexPage?.fields[fieldIdx]) {
366466
indexPage.fields[fieldIdx].type = enabledField ? originalPages[pageIdx].fields[fieldIdx].type : 'hidden';

0 commit comments

Comments
 (0)