Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Form validation hook (to use outside of onSubmit) #1006

Closed
candycanetrain opened this issue Aug 17, 2018 · 16 comments
Closed

Form validation hook (to use outside of onSubmit) #1006

candycanetrain opened this issue Aug 17, 2018 · 16 comments

Comments

@candycanetrain
Copy link

candycanetrain commented Aug 17, 2018

Prerequisites

  • [yes ] I have read the documentation;
  • [yes] In the case of a bug report, I understand that providing a SSCCE example is tremendously useful to the maintainers.

Description

I want to call the form validation function elsewhere (outside of clicking the submit button). Is there a way to do it?

My use case involves creating a drop down menu, where each selection displays a different json-schema-form. There's a submit button, but it's to submit a collection of form data. I want to be able to validate each form when the user switches a selection.

Expected behavior

A form validation hook is available for me to invoke outside of calling onSubmit.

Version

"react-jsonschema-form": "^1.0.2"

@glasserc
Copy link
Contributor

There is a Form#validate function. Does this not do what you want?

@anthony-bernardo
Copy link

anthony-bernardo commented Aug 27, 2018

@glasserc I got TypeError:

__WEBPACK_IMPORTED_MODULE_5_react_jsonschema_form___default.a.validate is not a function

Form.validate(value);

@llamamoray
Copy link
Collaborator

@xero88 I'm using the validate method on the form. Are you getting a ref to your form and calling validate on that?

@kylehalleman
Copy link

I am also running into this issue. Using a custom SchemaField instead of Form, but would like to call the library's validate on the SchemaField. Not seeing how to do this. Even tried re-working to use Form instead, but calling Form#validate needs to be on the instance and not the class (would be nice if it were possible to make validate a static).

@doncesarts
Copy link
Contributor

Please check this issue #500 , you will find examples of doing it.

@kylehalleman
Copy link

@doncesarts I think this is still a valid issue. Using the techniques outlined in #500, you're still triggering a submit, which just happens to validate. If validation passes, the form submits. That is not always desired, sometimes just a validation is required. Looking at the source code Form#validate requires an instance of the class. Would it be possible to make validate a static method on the Form class? Or expose some other way to only run validation without having to use a hack that also triggers submit?

Thank you for your time.

@glasserc
Copy link
Contributor

I still don't really understand the use case here. @kylehalleman Are you saying you don't actually use the Form class at all, but interact with the whole thing using SchemaField? Out of curiosity, why? I always expected the main entry point for this library would be Form, but we expose the different Field classes so you can subclass them if you want.

The Form#validate method isn't very complicated, especially once you subtract the stuff that is instance-related. It uses two functions (retrieveSchema and validateFormData) which are exported. I still don't understand why you would, but surely you could use those directly?

@llamamoray
Copy link
Collaborator

@kylehalleman what is your reason for not wanting to call validate on the form instance? Ultimately you could use ajv's validate method using your schema and form data. which is what the library does.

I'm also interested in your use case for using SchemaField over Form.

@kylehalleman
Copy link

kylehalleman commented Sep 27, 2018

We use both the Form class and SchemaField. We have a similar project to Kinto Formbuilder, where there is both a form for showing the fields that have been created and will be used by the end user, but also subforms that are used to edit those fields.

Specific to the need to validate without submitting, one of the custom widgets we created for editing a drop down list form field is the ability to add options to a select both via array fields and also using a textarea "bulk editor". The user can switch between both of those interfaces within the edit form.

In the scenario we've run into: A user enters two options in the array field, but they are duplicates and when hitting submit, gets validation errors for this. The user then switches to the "bulk editor" textarea, fixes the validation issue, and switches back to the array field layout, but the validation error messages persist. In this scenario we'd want to run validation when they switch from the bulk editor to the array field layout, without hitting submit on the form.

I can make a CodePen if that would help clear things up some more. However, I will try using the retrieveSchema and validateFormData methods as @glasserc described.

@llamamoray Thanks, I will look into using the ajv validate method directly if the above does not work. The reason I can't call validate on the form instance is where we would want to call the validate method is higher up in the component tree and even when rendering the Form component itself, we do not have access to the instance.

edit: Re-reading the React docs on refs, I was unaware refs could be attached to the component instance and not just the underlying DOM element. Due to the component tree we have set up, I'm not entirely sure we'll be able to get a ref to the Form element, but I will explore this option as well.

Thanks for your help, @glasserc and @llamamoray.

@candycanetrain
Copy link
Author

Since I had to implement it semi-urgently, I ended it up just using document.getElementById(${ID_NAME}').reportValidity(); to trigger a validation. It's not the best way though.

@vilchesalves
Copy link

Since I had to implement it semi-urgently, I ended it up just using document.getElementById(${ID_NAME}').reportValidity(); to trigger a validation. It's not the best way though.

Nice suggestion.

I ended up with something like:

const FormContainer = () => {
  const formRef = React.useRef(null);
  
  const checkValidation = () => {
    console.log(formRef.current.formElement.reportValidity());
  } 

  return (
    <Form
      ref={formRef}
    >
      <button onClick={checkValidation}>check validation</button>
    </Form>
  )
}

@saswat3115
Copy link

formRef.current.formElement.reportValidity()

This works great. Nice. Thanks for the suggestion. I was strugling like anything to find a way for this.

@grgicpetar
Copy link

formRef.current.formElement.reportValidity()

This works great. Nice. Thanks for the suggestion. I was strugling like anything to find a way for this.

I don't have the formElement object on the current ref. This is what I get when i console log it:

image

@AlexMachin1997
Copy link

How did you attach a ref to the actual

?

I've implemented this library at work and we created a custom component which uses the useTheme utility for generating our React-JSONSchema-Form stuff, though I would like to access the form props outside the Form component ie in an on the same page. Basically I want to save data before we do an action e.g. Expanding/Closing all Accordions on the page.

What happens currently is the form data is reset, but if I could get access to the current form data I could save the data before hand :)

Any guidance would be great 😉

@litzebauer
Copy link

litzebauer commented May 14, 2021

When I called Form#validate I get back the errors but the fields themselves are not showing the error messages. Is that the expected behavior? If so, how can I programmatically trigger validation that will have the form fields show the error state?

@heath-freenome
Copy link
Member

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests