Skip to content

feat: expose the Form Validator in the React, Angular and Vue bindings - #2646

Open
gigibiffi84 wants to merge 12 commits into
eclipsesource:masterfrom
gigibiffi84:feat/validator-prop-bindings
Open

gigibiffi84 wants to merge 12 commits into
eclipsesource:masterfrom
gigibiffi84:feat/validator-prop-bindings

Conversation

@gigibiffi84

Copy link
Copy Markdown

Part of #1498. Stacked on #2644 (Form Validator bridge) and #2645 (rules through the Form Validator); the diff shrinks to the last commit once those are merged.

What changed

The bindings expose the core validator option and the renderer sets evaluate rules through it.

  • React JsonForms: new validator?: ValidatorOption prop next to ajv, forwarded through JsonFormsStateProvider into init / updateCore and included in the update effect's dependencies.
  • Vue JsonForms: new validator prop (function or object), forwarded to init / updateCore and watched like ajv; new useValidator() composition returning the Form Validator bound to the schema, mirroring useAjv().
  • Angular JsonForms: new @Input() validator, stored in the initial core state and tracked in ngOnChanges; JsonFormsAngularService.updateCoreState takes an optional seventh validator argument (defaults to keeping the stored one, so existing callers are unaffected).
  • React renderer sets: withAjvProps (material and vanilla) additionally injects ruleValidator from the new getRuleValidator selector; the categorization layouts evaluate category visibility with ruleValidator ?? ajv. AjvProps.ajv is unchanged.
  • Angular Material: the categorization layout and mapStateToVisible call isVisible with getRuleValidator(state) instead of getAjv(state).
  • Examples: ExampleDescription and StateProps gain an optional validator; all five example apps pass it to JSON Forms. New example "Custom validator" with a dependency-free, handwritten Form Validator (required, lowercase strings, email contains a dot) and a schema-based rule, which exercises the Structural Matcher fallback since the validator has no matches.

For adopters

Nothing changes without the new prop. ajv keeps working everywhere; withAjvProps still provides ajv. Adopters who set validator get custom validation in all three bindings and rule evaluation without Ajv in core and in the shipped renderer sets. Known gap, deliberately left for a follow-up: vue-vuetify's AdditionalProperties passes only ajv to its nested form, so a nested form under a custom validator still validates with Ajv.

Tests

  • React: new JsonForms.test.tsx case asserting the factory reaches core, is called with the schema, and its issue renders as the control's error (29 tests green).
  • Vue: new JsonForms.spec.ts case asserting the option reaches core and its issue is stored as an error (4 tests green).
  • Angular: the package has no component test setup (ava dummy only); covered by the type-checked build and the Angular example app build.
  • Material and vanilla categorization tests green (37 and 14). Examples, the three bindings and the three renderer sets build; all five example apps build.

🤖 Generated with Claude Code

gigibiffi84 and others added 12 commits June 5, 2024 09:21
The SET_AJV reducer compiled the schema with the new Ajv instance but
never wrote it to state, so every later setSchema or re-enabled
validation silently went back to the previous instance.

Part of eclipsesource#1498

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ing them with Ajv

Combinator tab selection compiled every oneOf/anyOf/allOf branch with
Ajv and then ignored all errors except the structural keywords
required, additionalProperties, type, enum and const. The new
isStructuralMatch evaluates exactly those keywords itself, recursively
through properties, patternProperties, items, $ref, nested combinators
and if/then/else.

Tab selection therefore no longer depends on an Ajv instance or on
code generation, so it also works under a Content Security Policy
without unsafe-eval. Equivalence with the previous filtered-Ajv
behaviour is covered by tests comparing both approaches keyword by
keyword.

Part of eclipsesource#1498

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Adds the validation seam from issue eclipsesource#1498 as a non-breaking addition:
the `validator` init/updateCore option takes a FormValidatorFactory
`(schema) => FormValidator` or a FormValidator already bound to the
schema. The types mirror the FormValidator / ValidationIssue of the 4.x
presentation-model branch, restricted to synchronous results.

- The core reducer creates the Form Validator through the factory
  whenever the schema changes and caches it in `state.formValidator`;
  `state.validator` keeps holding the compiled Ajv function when Ajv
  validates, so existing consumers are unaffected.
- Issues from custom validators are converted to the Ajv error shape
  the rest of core and the renderers read (`issuesToErrors`): missing
  `key` becomes `custom`, `required` issues addressed to the missing
  property are split into parent path plus `params.missingProperty`,
  non-error severities are dropped and a missing `parentSchema` is
  resolved from the form schema.
- `createAjvValidator(ajv?)` is the built-in adapter;
  `compiledAjvValidator(validateFn)` wraps Ajv standalone code for CSP
  setups without unsafe-eval.
- `getValidator(state)` exposes the bound Form Validator.
- Switching to NoValidation via setValidationMode now also drops the
  cached validator, as init and updateCore already did.

Precedence: `validator` wins, otherwise `ajv`, otherwise the default
Ajv instance. Existing users notice nothing.

Part of eclipsesource#1498

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Resolved with the bridge's reducer (which already stores the Ajv
instance on setAjv), both util exports, and both groups of reducer
tests.
Schema based rule conditions were always evaluated with
ajv.validate(condition.schema, value), the last place where a custom
Form Validator did not apply.

- Widen the `ajv` parameter of isVisible, isEnabled, isReadonly, the
  eval* functions and Runtime.isVisible/isEnabled to RuleValidator: an
  Ajv instance (unchanged behaviour), a FormValidator (its `matches`,
  or the Structural Matcher when it has none), a FormValidatorFactory
  (one Form Validator per condition schema, cached) or undefined (the
  Structural Matcher alone).
- Add matchesConditionSchema and the getRuleValidator selector; core's
  own mappers pass getRuleValidator(state) instead of getAjv(state).

Part of eclipsesource#1498

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- React, Vue and Angular JsonForms gain a `validator` prop/input next to
  `ajv`, forwarded to init/updateCore; Vue adds useValidator();
  JsonFormsAngularService.updateCoreState takes an optional validator.
- Material and vanilla withAjvProps additionally inject `ruleValidator`
  (getRuleValidator), used by the categorization layouts; Angular
  Material evaluates category visibility with getRuleValidator too.
- ExampleDescription gains an optional `validator`, passed through by
  all five example apps; new "Custom validator" example with a
  dependency-free handwritten Form Validator and a schema-based rule.

Part of eclipsesource#1498

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@netlify

netlify Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for jsonforms-examples ready!

Name Link
🔨 Latest commit f2acbc0
🔍 Latest deploy log https://app.netlify.com/projects/jsonforms-examples/deploys/6ac686fd3592790008ed9f78
😎 Deploy Preview https://deploy-preview-2646--jsonforms-examples.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

This branch has not been deployed

No deployments
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