Skip to content

Feature/admin forth/1155/backend validation function le#511

Merged
SerVitasik merged 35 commits intonextfrom
feature/AdminForth/1155/backend-validation-function-le
Mar 31, 2026
Merged

Feature/admin forth/1155/backend validation function le#511
SerVitasik merged 35 commits intonextfrom
feature/AdminForth/1155/backend-validation-function-le

Conversation

@yaroslav8765
Copy link
Copy Markdown
Contributor

No description provided.

});
isValidating.value = false;
isValid.value = checkIfAnyColumnHasErrors();
}, 500);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to add ability set debounce period?

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support for backend-driven per-column validation via a custom validator callback, and wires the SPA create/edit flows to wait for async validation results before allowing saves.

Changes:

  • Extend column validation rules to support a custom validator callback and expose validator presence to the frontend.
  • Add /validate_columns REST endpoint and integrate it into SPA create/edit validation flow (including UI spinners and error display).
  • Refactor duplicated create/edit helpers into createEditUtils and update docs + dependency locks.

Reviewed changes

Copilot reviewed 12 out of 14 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
adminforth/types/Common.ts Adds validator to ValidationObject typing (backend custom validation hook).
adminforth/modules/restApi.ts Exposes validator presence in /get_resource and adds /validate_columns endpoint.
adminforth/spa/src/views/EditView.vue Updates save button state/spinner and uses shared save-prep helper.
adminforth/spa/src/views/CreateView.vue Updates save button state/spinner and uses shared save-prep helper.
adminforth/spa/src/components/ResourceForm.vue Tracks isValidating + columnsWithErrors and triggers backend validation.
adminforth/spa/src/components/GroupsTable.vue Passes validation state/errors down and updates required icon styling.
adminforth/spa/src/components/ColumnValueInputWrapper.vue Renders validation error + spinner near inputs during async validation.
adminforth/spa/src/utils/createEditUtils.ts New shared helpers for “scroll to invalid field” + save preparations.
adminforth/spa/src/utils/index.ts Re-exports new create/edit helpers.
adminforth/spa/src/utils.ts Re-exports new create/edit helpers (legacy barrel).
adminforth/documentation/docs/tutorial/03-Customization/13-standardPagesTuning.md Updates validation documentation with frontend vs backend validator guidance.
adminforth/spa/package.json Adds async-mutex and lodash.debounce dependencies.
adminforth/spa/pnpm-lock.yaml Lock updates for new deps and minor version bumps.
adminforth/spa/package-lock.json Lock updates for new deps and minor version bumps.
Files not reviewed (2)
  • adminforth/spa/package-lock.json: Language not supported
  • adminforth/spa/pnpm-lock.yaml: Language not supported
Comments suppressed due to low confidence (2)

adminforth/spa/src/views/CreateView.vue:226

  • saveRecordPreparations can return undefined when the form is invalid, but saveRecord() continues and dereferences interceptorsResult.extra, then proceeds to call /create_record. This can both throw at runtime and allow submitting invalid data. Add an early return when interceptorsResult is falsy and also check interceptorsResult.ok (similar to the previous implementation) before continuing.
async function saveRecord() {
  const interceptorsResult = await saveRecordPreparations(
    'create', 
    validatingMode, 
    resourceFormRef, 
    isValid, 
    t, 
    saving, 
    runSaveInterceptors, 
    record, 
    coreStore, 
    route
  );

  const requiredColumns = coreStore.resource?.columns.filter(c => c.required?.create === true) || [];
  const requiredColumnsToSkip = requiredColumns.filter(c => checkShowIf(c, record.value, coreStore.resource?.columns || []) === false);  

  const interceptorConfirmationResult = (interceptorsResult.extra as Record<string, any>)?.confirmationResult;
  const response = await callAdminForthApi({
    method: 'POST',
    path: `/create_record`,
    body: {
      resourceId: route.params.resourceId,
      record: record.value,
      requiredColumnsToSkip,
      meta: {
        ...(interceptorConfirmationResult ? { confirmationResult: interceptorConfirmationResult } : {}),
      },
    },
  });

adminforth/spa/src/views/EditView.vue:203

  • saveRecordPreparations may return undefined when validation fails, but saveRecord() immediately accesses interceptorsResult.ok. Guard against a falsy return value (early return) before checking .ok to avoid a runtime exception when the record is invalid.
async function saveRecord() {

  const interceptorsResult = await saveRecordPreparations(
    'edit', 
    validatingMode, 
    resourceFormRef, 
    isValid, 
    t, 
    saving, 
    runSaveInterceptors, 
    record, 
    coreStore, 
    route
  );

  if (!interceptorsResult.ok) {
    saving.value = false;
    if (interceptorsResult.error) showErrorTost(interceptorsResult.error);
    return;
  }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

delete columnsWithErrors.value[columnName];
}
}
const columnsToProcess = editableColumns.value.filter(col => res.validationResults[col.name] === undefined);
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In validateUsingUserValidationFunction, columnsToProcess is derived from editableColumns.value instead of the editableColumnsInner array that was actually validated and sent to the backend. If editableColumns changes while the request is in-flight (e.g., due to showIf changes), this can apply/clear errors for a different set of columns than the response corresponds to. Use editableColumnsInner (or the columns argument passed into the debounced function) when computing columnsToProcess.

Suggested change
const columnsToProcess = editableColumns.value.filter(col => res.validationResults[col.name] === undefined);
const columnsToProcess = editableColumnsInner.filter(col => res.validationResults[col.name] === undefined);

Copilot uses AI. Check for mistakes.
],
```

>Better avoid using of custom validator, because every time change field (after failed first save attempt), it will make an API call
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The warning sentence is ungrammatical and a bit unclear: "Better avoid using of custom validator, because every time change field...". Rephrase to something like "Avoid using a custom validator because every time you change a field...".

Suggested change
>Better avoid using of custom validator, because every time change field (after failed first save attempt), it will make an API call
>Avoid using a custom validator because every time you change a field (after a failed first save attempt), it will make an API call.

Copilot uses AI. Check for mistakes.
Comment on lines +80 to +92
import { type AdminForthComponentDeclarationFull } from '@/types/Common.js';
import type { AdminForthResourceColumn } from '@/types/Back';
import { scrollToInvalidField, saveRecordPreparations } from '@/utils';
import { Spinner } from '@/afcl'
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are several imports that are now unused after moving validation helpers to saveRecordPreparations (e.g., scrollToInvalidField, AdminForthResourceColumn, and also watch/nextTick/computed which are only imported). These will be flagged by the SPA ESLint config; please remove the unused imports.

Copilot uses AI. Check for mistakes.
yaroslav8765 and others added 10 commits March 30, 2026 13:14
…y-to-improve-styles-for

Feature/admin forth/1334/lets try to improve styles for
…minForth/1155/backend-validation-function-le
… ValidationObject

- Refactored the applyRegexValidation function to improve readability by storing the regExp in a variable before usage.
- Made the regExp and message properties optional in the ValidationObject type to allow for more flexible validation scenarios.
- Cleaned up imports in CreateView.vue by removing unused imports to enhance code clarity and maintainability.

https://web.tracklify.com/project/2b7ZVgE5/AdminForth/1155/9bItdaNO/backend-validation-function-le
@SerVitasik SerVitasik merged commit 62f4246 into next Mar 31, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants