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

Rerun validation on submit #559

Closed
CodeWithOz opened this issue Jul 10, 2019 · 4 comments
Closed

Rerun validation on submit #559

CodeWithOz opened this issue Jul 10, 2019 · 4 comments

Comments

@CodeWithOz
Copy link
Contributor

Are you submitting a bug report or a feature request?

Feature request

What is the current behavior?

Once a form's fields have been validated, submitting doesn't trigger a rerun of the validation.

What is the expected behavior?

I would like a way to trigger a rerun of the validation when the form is submitted. I have tried using the beforeSubmit listener from the final-form-submit-listener package but it only gives access to the FormApi object. I tried using the pauseValidation and resumeValidation functions from FormApi but they couldn't achieve what I want, or maybe I'm not using them correctly. I have a feeling it's painfully obvious how to do this, but I can't figure it out. 😩

Sandbox Link

See this Sandbox.

What's your environment?

Final form: 4.13.1
React final form: 4.1.0

Other information

I have a form field whose value can become invalid if it's not submitted within a particular timeframe. It's not async; I'm just trying to cover a scenario in which the user doesn't click submit for a while, and when they eventually do, the value would have become invalid. Final form remembers the result of the validation that happens immediately after the value is changed, which means that the unchanged value remains valid regardless of how much time passes between the validation and the submission. This is the behavior I want to hook into and change; the intervening time matters in my use case.

Thanks!

@CodeWithOz
Copy link
Contributor Author

Some additional information:

  • This is for a time picker, and if you're picking times for today, you may pick a time that is 15 minutes from now. It's valid now because it's currently in the future. If you don't touch the form for the next 20 minutes then click submit, the submission should be prevented because your selected time is now 5 minutes in the past.
  • I have considered just adding the validation directly in the submit handler. This is not ideal for me because Final Form doesn't receive the errors and pass them to the meta object for the form fields. My codebase is complex and relies heavily upon the meta object to display error messages. Trying to replicate that functionality in the submit handler may work but it's hacky and goes against the convention used throughout the codebase.

@CodeWithOz
Copy link
Contributor Author

CodeWithOz commented Jul 12, 2019

So I have found a way to do this! 🎉
I use a mutator and use it's changeValue function to 'change' the value of the relevant field (I supply the same value). This in turn notifies all relevant parties of the change to the form's state, and a validation is triggered. The key is to call the mutator inside the submit handler, which therefore ensures that the validation is performed when the form is submitted. Have a look at this new Sandbox.

The relevant bits are as follows:

// this is a stateful component
...
...
  mutateValue([name], state, { changeValue }) {
    // change the value to the same value, thus
    // triggering a revalidation of the same value
    changeValue(state, name, value => value);
  }

  handleSubmit(values) {
    alert("submitted");
  }

  render() {
    return (
  ...
  ...
        <Form
          onSubmit={this.handleSubmit}
          mutators={{ mutateValue: this.mutateValue }}
          render={({
            handleSubmit,
            form: {
              mutators: { mutateValue }
            }
          }) => {
            const mutateBeforeSubmit = values => {
              // supply the name of the relevant form field
              mutateValue("revalidate");
              // submit handler gets called if revalidation still passes
              handleSubmit(values);
            };
            return (
              <form onSubmit={mutateBeforeSubmit}>
              ...
              ...
              </form>
            );
          }}
        />
        ...
        ...

Importantly, this plays nicely with meta, which is exactly what I need.

Although this solves my problem, I will leave the issue open in case there's a better/simpler/"more official" way of achieving this. Thanks in advance! 😄

@erikras
Copy link
Member

erikras commented Jul 12, 2019

I guess I'll reproduce the answer I gave on Stack Overflow...


Library author here. I'm always fascinated by new ways people can invalidate my assumptions. I mean that in a sincerely positive way, as it results in learning.

🏁 Final Form makes the assumption that your validation functions are "pure" or "idempotent", i.e. will always return the same result when given the same values. This is why it doesn't run the synchronous validation again (just to double check) before allowing the submission: because it's already stored the results of the last time it ran it. By using an outside timer, you've invalidated that assumption.

If you have a better/simpler/"more official" solution, I'd still love to see it!

No need for mutators or decorators for this problem.

The more official way to do this would be to run the check (you could even reuse this.validate) in onSubmit. The only tricky part is that the error will come back as meta.submitError, so you need to check for both when displaying your error. Like so:

Edit Force revalidation on submit (React Final Form)

@erikras erikras closed this as completed Jul 12, 2019
@rendomnet
Copy link

rendomnet commented Nov 13, 2019

@erikras but will fields be revalidated and show field error messages inside of them?
Or we just receive list of errors?
I have validate props on specific fields that are depending on state change. And when state changes the fields are not revalidated.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 5, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants