Skip to content

Commit 7a2b434

Browse files
committed
feat: add scroll to invalid fields and error notification when user tries to save invalid record
1 parent 82a83a2 commit 7a2b434

File tree

3 files changed

+31
-2
lines changed

3 files changed

+31
-2
lines changed

adminforth/spa/src/components/GroupsTable.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
@update:emptiness="customComponentsEmptiness[$event.name] = $event.value"
5656
:readonly="readonlyColumns?.includes(column.name)"
5757
/>
58-
<div v-if="columnError(column) && validating" class="mt-1 text-xs text-lightInputErrorColor dark:text-darkInputErrorColor">{{ columnError(column) }}</div>
58+
<div v-if="columnError(column) && validating" class="af-invalid-field-message mt-1 text-xs text-lightInputErrorColor dark:text-darkInputErrorColor">{{ columnError(column) }}</div>
5959
<div v-if="column.editingNote && column.editingNote[mode]" class="mt-1 text-xs text-lightFormFieldTextColor dark:text-darkFormFieldTextColor">{{ column.editingNote[mode] }}</div>
6060
</td>
6161
</tr>

adminforth/spa/src/components/ResourceForm.vue

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,4 +377,9 @@ watch(() => isValid.value, (value) => {
377377
emit('update:isValid', value);
378378
});
379379
380+
defineExpose({
381+
columnError,
382+
editableColumns,
383+
})
384+
380385
</script>

adminforth/spa/src/views/CreateView.vue

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767

6868
<ResourceForm
6969
v-else
70+
ref="resourceFormRef"
7071
:record="record"
7172
:resource="coreStore.resource!"
7273
@update:record="onUpdateRecord"
@@ -98,14 +99,15 @@ import SingleSkeletLoader from '@/components/SingleSkeletLoader.vue';
9899
import { useCoreStore } from '@/stores/core';
99100
import { callAdminForthApi, getCustomComponent,checkAcessByAllowedActions, initThreeDotsDropdown } from '@/utils';
100101
import { IconFloppyDiskSolid } from '@iconify-prerendered/vue-flowbite';
101-
import { onMounted, ref, watch } from 'vue';
102+
import { onMounted, ref, watch, nextTick } from 'vue';
102103
import { useRoute, useRouter } from 'vue-router';
103104
import { computed } from 'vue';
104105
import { showErrorTost } from '@/composables/useFrontendApi';
105106
import ThreeDotsMenu from '@/components/ThreeDotsMenu.vue';
106107
import adminforth from '@/adminforth';
107108
import { useI18n } from 'vue-i18n';
108109
import { type AdminForthComponentDeclarationFull } from '@/types/Common.js';
110+
import type { AdminForthResourceColumn } from '@/types/Back';
109111
110112
const isValid = ref(false);
111113
const validating = ref(false);
@@ -122,6 +124,8 @@ const coreStore = useCoreStore();
122124
123125
const { t } = useI18n();
124126
127+
const resourceFormRef = ref<InstanceType<typeof ResourceForm> | null>(null);
128+
125129
const createSaveButtonInjection = computed<AdminForthComponentDeclarationFull | null>(() => {
126130
const raw: any = coreStore.resourceOptions?.pageInjections?.create?.saveButton as any;
127131
if (!raw) return null;
@@ -180,6 +184,8 @@ onMounted(async () => {
180184
async function saveRecord(opts?: { confirmationResult?: any }) {
181185
if (!isValid.value) {
182186
validating.value = true;
187+
await nextTick();
188+
scrollToInvalidField();
183189
return;
184190
} else {
185191
validating.value = false;
@@ -217,5 +223,23 @@ async function saveRecord(opts?: { confirmationResult?: any }) {
217223
}
218224
}
219225
226+
function scrollToInvalidField() {
227+
let columnsWithErrors: {column: AdminForthResourceColumn, error: string}[] = [];
228+
for (const column of resourceFormRef.value?.editableColumns || []) {
229+
const error = resourceFormRef.value?.columnError(column);
230+
if (error) {
231+
columnsWithErrors.push({column, error});
232+
}
233+
}
234+
const errorMessage = t('Failed to save. Please fix errors for the following fields:') + '<ul class="mt-2 list-disc list-inside">' + columnsWithErrors.map(c => `<li><strong>${c.column.label || c.column.name}</strong>: ${c.error}</li>`).join('') + '</ul>';
235+
adminforth.alert({
236+
messageHtml: errorMessage,
237+
variant: 'danger'
238+
});
239+
const firstInvalidElement = document.querySelector('.af-invalid-field-message');
240+
if (firstInvalidElement) {
241+
firstInvalidElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
242+
}
243+
}
220244
221245
</script>

0 commit comments

Comments
 (0)