From f0c2e35cf39b2353f6d4265a370ab4f1824dfa71 Mon Sep 17 00:00:00 2001 From: Heath Chiavettone Date: Fri, 16 Sep 2022 10:23:11 -0700 Subject: [PATCH 1/2] fix: Add programmatic form validation support - Updated the `Form` to add a new `validateForm()` function by refactoring that portion of the code out of the `onSubmit()` callback - Updated the playground to add a new `Prog. Validate` button to programmatically validate a form - Moved the `Share` button onto the next line and changed `Programmatically Submit` button to `Prog. Submit` - Added an alert when the form is submitted - Updated the `validation.md` documentation with this new capability - Updated the `CHANGELOG.md` file accordingly --- CHANGELOG.md | 3 + docs/usage/validation.md | 27 ++++++ packages/core/src/components/Form.tsx | 124 ++++++++++++++------------ packages/playground/src/app.js | 19 +++- 4 files changed, 113 insertions(+), 60 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ba8950d17..8b1be0d9ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ should change the heading of the (upcoming) version to include a major version b - Updated the `FieldErrorTemplate` to remove the explicit typing of the `error` to string to support the two options ## @rjsf/core +- Implemented programmatic validation via new `validateForm()` method on `Form`, fixing (https://github.com/rjsf-team/react-jsonschema-form/issues/2755, https://github.com/rjsf-team/react-jsonschema-form/issues/2552, https://github.com/rjsf-team/react-jsonschema-form/issues/2381, https://github.com/rjsf-team/react-jsonschema-form/issues/2343, https://github.com/rjsf-team/react-jsonschema-form/issues/1006, https://github.com/rjsf-team/react-jsonschema-form/issues/246) - Updated the `FieldErrorTemplate` to remove the explicit typing of the `error` to string to support the two options ## @rjsf/semantic-ui @@ -31,6 +32,8 @@ should change the heading of the (upcoming) version to include a major version b ## Dev / docs / playground - Updated the `custom-templates.md` file to add the missing asterisk to the new `FieldErrorTemplate` and `FieldHelpTemplate` +- Updated the playground to add a new button for programmatically validating a form +- Also updated the `validation.md` documentation to describe how to programmatically validate a form # 5.0.0-beta.8 diff --git a/docs/usage/validation.md b/docs/usage/validation.md index 51b5af227b..f5e9bbad6e 100644 --- a/docs/usage/validation.md +++ b/docs/usage/validation.md @@ -34,6 +34,33 @@ render(( ), document.getElementById("app")); ``` +## Validate form programmatically + +It is possible to programmatically validate a form using the `validateForm()` function on `Form`. +Add a `ref` to your `Form` component and call the `validateForm()` method to validate the form programmatically. +The `validateForm()` method returns true if the form is valid, false otherwise. +If you have provided an `onError` callback it will be called with the list of errors when the `validatorForm()` method returns false. + +```jsx +import { createRef } from "react" +import validator from "@rjsf/validator-ajv6"; + +const formRef = createRef(); +const onError = (errors) => alert(errors); + +const schema = { + type: "string" +}; + +render(( +
+), document.getElementById("app")); + +if (formRef.current.validateForm()) { + alert("Form is valid"); +} +``` + ## HTML5 Validation By default, the form uses HTML5 validation. This may cause unintuitive results because the HTML5 validation errors (such as when a field is `required`) may be displayed before the form is submitted, and thus these errors will display differently from the react-jsonschema-form validation errors. You can turn off HTML validation by setting the `noHtml5Validate` to `true`. diff --git a/packages/core/src/components/Form.tsx b/packages/core/src/components/Form.tsx index 8fbde31526..7476dd8a1a 100644 --- a/packages/core/src/components/Form.tsx +++ b/packages/core/src/components/Form.tsx @@ -613,8 +613,7 @@ export default class Form extends Component< } event.persist(); - const { omitExtraData, extraErrors, noValidate, onSubmit, onError } = - this.props; + const { omitExtraData, extraErrors, noValidate, onSubmit } = this.props; let { formData: newFormData } = this.state; const { schema, schemaUtils } = this.state; @@ -631,63 +630,31 @@ export default class Form extends Component< newFormData = this.getUsedFormData(newFormData, fieldNames); } - if (!noValidate) { - const schemaValidation = this.validate(schemaUtils, newFormData); - let errors = schemaValidation.errors; - let errorSchema = schemaValidation.errorSchema; - const schemaValidationErrors = errors; - const schemaValidationErrorSchema = errorSchema; - if (errors.length > 0) { - if (extraErrors) { - const merged = schemaUtils.mergeValidationData( - schemaValidation, - extraErrors - ); - errorSchema = merged.errorSchema; - errors = merged.errors; - } - this.setState( - { - errors, - errorSchema, - schemaValidationErrors, - schemaValidationErrorSchema, - }, - () => { - if (onError) { - onError(errors); - } else { - console.error("Form validation failed", errors); - } + if (noValidate || this.validateForm()) { + // There are no errors generated through schema validation. + // Check for user provided errors and update state accordingly. + const errorSchema = extraErrors || {}; + const errors = extraErrors + ? schemaUtils.getValidator().toErrorList(extraErrors) + : []; + this.setState( + { + formData: newFormData, + errors, + errorSchema, + schemaValidationErrors: [], + schemaValidationErrorSchema: {}, + }, + () => { + if (onSubmit) { + onSubmit( + { ...this.state, formData: newFormData, status: "submitted" }, + event + ); } - ); - return; - } - } - - // There are no errors generated through schema validation. - // Check for user provided errors and update state accordingly. - const errorSchema = extraErrors || {}; - const errors = extraErrors - ? schemaUtils.getValidator().toErrorList(extraErrors) - : []; - this.setState( - { - formData: newFormData, - errors, - errorSchema, - schemaValidationErrors: [], - schemaValidationErrorSchema: {}, - }, - () => { - if (onSubmit) { - onSubmit( - { ...this.state, formData: newFormData, status: "submitted" }, - event - ); } - } - ); + ); + } }; /** Returns the registry for the form */ @@ -723,6 +690,49 @@ export default class Form extends Component< } } + /** Programmatically validate the form. If `onError` is provided, then it will be called with the list of errors the + * same way as would happen on form submission. + * + * @returns - True if the form is valid, false otherwise. + */ + validateForm() { + const { extraErrors, onError } = this.props; + const { formData } = this.state; + const { schemaUtils } = this.state; + const schemaValidation = this.validate(schemaUtils, formData); + let errors = schemaValidation.errors; + let errorSchema = schemaValidation.errorSchema; + const schemaValidationErrors = errors; + const schemaValidationErrorSchema = errorSchema; + if (errors.length > 0) { + if (extraErrors) { + const merged = schemaUtils.mergeValidationData( + schemaValidation, + extraErrors + ); + errorSchema = merged.errorSchema; + errors = merged.errors; + } + this.setState( + { + errors, + errorSchema, + schemaValidationErrors, + schemaValidationErrorSchema, + }, + () => { + if (onError) { + onError(errors); + } else { + console.error("Form validation failed", errors); + } + } + ); + return false; + } + return true; + } + /** Renders the `Form` fields inside the | `tagName` or `_internalFormWrapper`, rendering any errors if * needed along with the submit button or any children of the form. */ diff --git a/packages/playground/src/app.js b/packages/playground/src/app.js index aea6cce4e0..1ef4d36cde 100644 --- a/packages/playground/src/app.js +++ b/packages/playground/src/app.js @@ -487,16 +487,28 @@ class Playground extends Component { validator={validator} select={this.onValidatorSelected} /> - - + + +
+
@@ -578,6 +590,7 @@ class Playground extends Component { onSubmit={({ formData }, e) => { console.log("submitted formData", formData); console.log("submit event", e); + window.alert("Form submitted"); }} fields={{ geo: GeoPosition }} customValidate={validate} From e8ad5e0e263d9db8c0a0e7878ee49068655108fe Mon Sep 17 00:00:00 2001 From: Heath Chiavettone Date: Fri, 16 Sep 2022 11:42:46 -0700 Subject: [PATCH 2/2] - Update the release document generation to use the main branch --- .github/workflows/release-docs.yml | 2 ++ CHANGELOG.md | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release-docs.yml b/.github/workflows/release-docs.yml index 8921ac0aea..3b4fd8c31c 100644 --- a/.github/workflows/release-docs.yml +++ b/.github/workflows/release-docs.yml @@ -25,6 +25,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 + with: + ref: main - name: Setup Python uses: actions/setup-python@v3 with: diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b1be0d9ee..cd0b2c8488 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,8 +21,8 @@ should change the heading of the (upcoming) version to include a major version b - Updated the `FieldErrorTemplate` to remove the explicit typing of the `error` to string to support the two options ## @rjsf/core -- Implemented programmatic validation via new `validateForm()` method on `Form`, fixing (https://github.com/rjsf-team/react-jsonschema-form/issues/2755, https://github.com/rjsf-team/react-jsonschema-form/issues/2552, https://github.com/rjsf-team/react-jsonschema-form/issues/2381, https://github.com/rjsf-team/react-jsonschema-form/issues/2343, https://github.com/rjsf-team/react-jsonschema-form/issues/1006, https://github.com/rjsf-team/react-jsonschema-form/issues/246) - Updated the `FieldErrorTemplate` to remove the explicit typing of the `error` to string to support the two options +- Implemented programmatic validation via new `validateForm()` method on `Form`, fixing (https://github.com/rjsf-team/react-jsonschema-form/issues/2755, https://github.com/rjsf-team/react-jsonschema-form/issues/2552, https://github.com/rjsf-team/react-jsonschema-form/issues/2381, https://github.com/rjsf-team/react-jsonschema-form/issues/2343, https://github.com/rjsf-team/react-jsonschema-form/issues/1006, https://github.com/rjsf-team/react-jsonschema-form/issues/246) ## @rjsf/semantic-ui - Updated the `FieldErrorTemplate` to use the `children` variation of the `List.Item` that supports ReactElement