Skip to content

Commit 6073982

Browse files
committed
feat: add custom validation functionality for resource columns[3]
1 parent e7affbd commit 6073982

File tree

3 files changed

+45
-11
lines changed

3 files changed

+45
-11
lines changed

adminforth/spa/src/components/ColumnValueInputWrapper.vue

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,14 @@
5353
@update:inValidity="$emit('update:inValidity', { name: column.name, value: $event })"
5454
@update:emptiness="$emit('update:emptiness', { name: column.name, value: $event })"
5555
/>
56+
<Spinner v-if="shouldWeShowSpinner" class="w-4 absolute top-1 left-2"/>
5657
</template>
5758

5859
<script setup lang="ts">
5960
import { IconPlusOutline } from '@iconify-prerendered/vue-flowbite';
6061
import ColumnValueInput from "./ColumnValueInput.vue";
61-
import { ref, nextTick } from 'vue';
62+
import { ref, watch, nextTick } from 'vue';
63+
import { Spinner } from '@/afcl';
6264
6365
const props = defineProps<{
6466
source: 'create' | 'edit',
@@ -69,7 +71,28 @@
6971
unmasked: any,
7072
setCurrentValue: Function,
7173
readonly?: boolean,
74+
columnsWithErrors: Record<string, string>,
75+
isValidating: boolean
7276
}>();
77+
78+
const shouldWeShowSpinner = ref(false);
79+
80+
81+
watch(() => props.currentValues[props.column.name], async (newVal) => {
82+
console.log('Current value for column', props.column.name, 'changed to', newVal);
83+
await nextTick();
84+
if (props.isValidating) {
85+
shouldWeShowSpinner.value = true;
86+
}
87+
});
88+
89+
watch(() => [props.columnsWithErrors[props.column.name], props.isValidating], () => {
90+
if (props.isValidating) {
91+
shouldWeShowSpinner.value = false;
92+
} else {
93+
shouldWeShowSpinner.value = false;
94+
}
95+
});
7396
7497
const emit = defineEmits(['update:unmasked', 'update:inValidity', 'update:emptiness', 'focus-last-input']);
7598

adminforth/spa/src/components/GroupsTable.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@
5656
@update:inValidity="customComponentsInValidity[$event.name] = $event.value"
5757
@update:emptiness="customComponentsEmptiness[$event.name] = $event.value"
5858
:readonly="readonlyColumns?.includes(column.name)"
59+
:columnsWithErrors="columnsWithErrors"
60+
:isValidating="isValidating"
5961
/>
6062
<div v-if="columnsWithErrors[column.name] && validating" class="af-invalid-field-message mt-1 text-xs text-lightInputErrorColor dark:text-darkInputErrorColor">{{ columnsWithErrors[column.name] }}</div>
6163
<div v-if="column.editingNote && column.editingNote[mode]" class="mt-1 text-xs text-lightFormFieldTextColor dark:text-darkFormFieldTextColor">{{ column.editingNote[mode] }}</div>

adminforth/spa/src/components/ResourceForm.vue

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ const columnOffsets = reactive<Record<string, number>>({});
112112
const columnEmptyResultsCount = reactive<Record<string, number>>({});
113113
const columnsWithErrors = ref<Record<string, string>>({});
114114
const isValidating = ref(false);
115+
const isValid = ref(true);
115116
116117
const columnError = (column: AdminForthResourceColumnCommon) => {
117118
const val = computed(() => {
@@ -351,21 +352,31 @@ function checkIfColumnHasError(column: AdminForthResourceColumnCommon) {
351352
}
352353
}
353354
354-
const isValid = computed(async () => {
355+
const checkIfAnyColumnHasErrors = () => {
356+
return Object.keys(columnsWithErrors.value).length > 0 ? false : true;
357+
}
358+
359+
const debouncedValidation = debounce(async (columns: AdminForthResourceColumnCommon[]) => {
360+
await mutex.runExclusive(async () => {
361+
await validateUsingUserValidationFunction(columns);
362+
});
363+
isValidating.value = false;
364+
isValid.value = checkIfAnyColumnHasErrors();
365+
}, 500);
366+
367+
watch(() => [editableColumns.value, props.validating], async () => {
355368
editableColumns.value?.forEach(column => {
356369
checkIfColumnHasError(column);
357370
});
358371
359372
isValidating.value = true;
360-
let isValid = true;
361373
if (props.validating) {
362374
//Here I need to add debounce
363-
await mutex.runExclusive(async () => {
364-
isValid = await validateUsingUserValidationFunction(editableColumns.value);
365-
});
375+
debouncedValidation(editableColumns.value);
376+
} else {
377+
isValidating.value = false;
378+
isValid.value = checkIfAnyColumnHasErrors();
366379
}
367-
isValidating.value = false;
368-
return Object.keys(columnsWithErrors.value).length > 0 ? false : true;
369380
});
370381
371382
@@ -417,7 +428,7 @@ watch(() => isValid.value, async (value) => {
417428
emit('update:isValid', resolvedValue);
418429
});
419430
420-
async function validateUsingUserValidationFunction(editableColumnsInner: AdminForthResourceColumnCommon[]): Promise<boolean> {
431+
async function validateUsingUserValidationFunction(editableColumnsInner: AdminForthResourceColumnCommon[]): Promise<void> {
421432
const doesUserHaveCustomValidation = props.resource.columns.some(column => column.validation && column.validation.some((val: any) => val.customValidator));
422433
if (doesUserHaveCustomValidation) {
423434
try {
@@ -450,10 +461,8 @@ async function validateUsingUserValidationFunction(editableColumnsInner: AdminFo
450461
451462
} catch (e) {
452463
console.error('Error during custom validation', e);
453-
return false;
454464
}
455465
}
456-
return true;
457466
}
458467
459468
defineExpose({

0 commit comments

Comments
 (0)