rjsf-team / react-jsonschema-form

A React component for building Web forms from JSON Schema.
https://rjsf-team.github.io/react-jsonschema-form/
Apache License 2.0
14.33k stars 2.19k forks source link

Cannot check for existing errors on field in CustomValidate #4284

Open TheOneTheOnlyJJ opened 2 months ago

TheOneTheOnlyJJ commented 2 months ago

Prerequisites

What theme are you using?

core

Version

5.20.0

Current Behavior

I have a username field in my form that I want to invalidate if it is not unique. I check its uniqueness with an API call, which always runs in my CustomValidate function. However, it would be more efficient only to run it if there are no other prior errors on that field (I have a pattern in the JSON schema that disallows certain characters). I am trying to do a simple if based on the errors.username.__errors variable, but no matter in which configuration I write the condition, I can only get it to always be true or never be true, regardless of the presence of other errors.

Expected Behavior

I expect a check such as if (!errors.username.__errors || errors.username.__errors.length === 0) to be true if there are no errors associated to the username field, and false if there is at least one.

Steps To Reproduce

No response

Environment

- OS: Windows 10
- Node: 20.15.0
- npm: 10.8.2

Anything else?

No response

nickgros commented 2 months ago

@TheOneTheOnlyJJ Could you create a CodeSandbox reproduction that demonstrates that __errors is not the value you would expect?

TheOneTheOnlyJJ commented 2 months ago

Sure, here you go: https://codesandbox.io/p/sandbox/rjsf-field-errors-3ndqph Observe the errors when inputting a valid string according to the specified pattern, and then an invalid one. For simplicity, I changed the pattern to allow lowercase ASCII letters only. I have played around with the if condition, but I cannot get it to work.

TheOneTheOnlyJJ commented 1 month ago

@nickgros Is the example I provided not satisfactory? Can the "needs reproducible example" label be removed now?

nickgros commented 1 month ago

@TheOneTheOnlyJJ sorry for the delay. I took a closer look and discovered that we don't pass existing errors to customValidate, so you cannot use that to add rules based on other errors. We run the rules through the validator, then we run customValidate, and then we merge the two.

You might be able to use the transformErrors function, with something like this:

import { ErrorTransformer } from "@rjsf/utils";

const transformErrors: ErrorTransformer = (errors) => {
  // Skip if no form data or errors
  let hasErrorInUserName = false;
  errors.forEach((e) => {
    if (e.property === ".username") {
      hasErrorInUserName = true;
    }
  });

  if (!hasErrorInUserName) {
    // Synchronous API call...
    errors.push({
      name: "Username taken",
      stack: ".username",
      message: "Username exists in system",
    });
  }

  return errors;
};