Skip to content

Add form field validation to BaseForm/ActionForm#2963

Open
nfdiop wants to merge 10 commits intomainfrom
nfdiop/add-form-validation
Open

Add form field validation to BaseForm/ActionForm#2963
nfdiop wants to merge 10 commits intomainfrom
nfdiop/add-form-validation

Conversation

@nfdiop
Copy link
Copy Markdown
Contributor

@nfdiop nfdiop commented Apr 8, 2026

Summary

  • Wire react-hook-form validation using onTouched mode (validate on blur, revalidate on change after first error)
  • Add extractValidationRules utility that derives RHF rules from field constraint props (min/max, minLength/maxLength, maxSize, required)
  • Show red border + error message on invalid fields via data-invalid attribute and CSS tokens
  • Submit button stays enabled with error summary tooltip when form has validation errors
  • Export ValidationError discriminated union so users can customize messages via onValidationError
  • Clamp NumberInputField stepper to min/max bounds

Test plan

  • Unit tests for extractValidationRules (19 tests covering all field types, custom validate, onValidationError overrides)
  • Integration tests in BaseForm.test.tsx (required error on blur, minLength error, error clears on fix, prevents submit when invalid)
  • Typecheck passes (pnpm turbo typecheck --filter=@osdk/react-components)
  • All existing tests still pass
  • Manual testing with form page for visual error states

Notes

  • Tracking more validation to do as a FLUP. For example for integer fields, we need to validate the shape
Screenshot 2026-04-10 at 10 11 41 Screenshot 2026-04-10 at 10 11 50 Screenshot 2026-04-10 at 10 11 54 Screenshot 2026-04-10 at 10 13 41 Screenshot 2026-04-10 at 10 13 50

nfdiop added 2 commits April 8, 2026 12:14
Wire react-hook-form validation using onTouched mode with rule extraction
from field constraint props (min/max, minLength/maxLength, maxSize, required).
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 8, 2026

size-limit report 📦

Path Size Change
@osdk/api 432 B 0%
@osdk/client 26.42 kB 0%
@osdk/oauth 6.52 kB 0%
@osdk/react 513 B 0%
@osdk/react/experimental 52.44 kB 0%
@osdk/react/experimental/admin 2.43 kB 0%
@osdk/react-components 10 B 0%
@osdk/react-components/experimental 482.34 kB +0.17% 🔺
@osdk/react-components/primitives 40.46 kB 0%
@osdk/widget.client-react 10.56 kB 0%

nfdiop added 3 commits April 8, 2026 15:29
- Don't block submit on validation errors (use trigger() + always submit)
- Switch from data-invalid to aria-invalid for accessibility
- Move rules computation back to FieldBridge
- Make FormFieldRenderer onBlur/error required, extract common props
- Rename fieldState error to fieldError in FieldBridge
- Enforce maxSize in FilePickerField by filtering oversized files
- Extract ActionButton into reusable variable in SubmitButton
- Add tests for required/non-required submission scenarios
- Rename changeset
formTitle?: string;
fieldDefinitions: ReadonlyArray<RendererFieldDefinition>;
onSubmit: (formState: Record<string, unknown>) => void;
onSubmit: (formState: Record<string, unknown>) => Promise<void> | void;
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.

so that we can await

* overflow: visible to allow the path to be rendered outside the
* clipping boundary of the SVG container.
*/
& svg {
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.

Curious if there is a better way to fix

- Add useAsyncAction hook tests (7 tests)
- Improve extractValidationRules tests: exact assertions for dates/file
  size, getValidateFns helper to reduce casting boilerplate
- Remove FieldCommonProps, pass error directly as named prop
- Consolidate onBlur logic in FieldBridge (the only RHF-aware module):
  container-aware blur filtering + touch-on-change for select-like fields
- Revert FilePickerField handleInputChange to original form
const submissionErrorMessage = submissionError != null
? submissionError instanceof Error
? submissionError.message
// TODO: provide better error message
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.

Tracking

* Return `undefined` if valid, or an error message string if invalid.
*/
validate?: (value: FieldValueType<Q, K>) => Promise<boolean>;
validate?: (value: FieldValueType<Q, K>) => Promise<string | undefined>;
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.

I prefer when users return a string we can use to provide an explanation. Fine to change since the API is not released yet

* A discriminated union describing which validation rule failed and the
* constraint data the user needs to build a meaningful error message.
*/
export type ValidationError =
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.

Changed so the error message can use the validation config

* Returns a ref whose `.current` is `true` while the component is mounted
* and `false` after unmount. Use to guard async state updates.
*/
export function useIsMounted(): Readonly<React.RefObject<boolean>> {
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.

Simple hook so no tests added

@nfdiop nfdiop marked this pull request as ready for review April 10, 2026 09:11
@nfdiop nfdiop force-pushed the nfdiop/add-form-validation branch from 4f57a1c to 7f402ae Compare April 10, 2026 11:34
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.

1 participant