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

Offer non-immediate validation in Fable.Simple.Form #42

Open
mattgallagher92 opened this issue Oct 14, 2023 · 3 comments
Open

Offer non-immediate validation in Fable.Simple.Form #42

mattgallagher92 opened this issue Oct 14, 2023 · 3 comments

Comments

@mattgallagher92
Copy link
Contributor

The current validation strategies offered in Fable.Form.Simple are ValidateOnBlur and ValidateOnSubmit. Based on their names, I assumed that they would only validate when a field is blurred or the form is submitted. However, the behaviour instead seems to be that validation is first triggered after blur/submit, but is then triggered after every subsequent change to a field. I would like an option that results in validation only being triggered on submit.

I propose that the following would be suitable cases for the Fable.Form.Simple.Form.View.Validation type:

  • ValidateImmediately (trigger validation after every field state change)
  • ValidateOnBlurThenImmediately (currently known as ValidateOnBlur)
  • ValidateOnBlurOnly (trigger only after blur, not while still focused on a field)
  • ValidateOnSubmitThenImmediately (currently known as ValidateOnSubmit)
  • ValidateOnSubmitOnly (trigger only when submitting, not before)

Another possible case could be ValidateOnSubmitThenOnBlur, but my guess is that that wouldn't be very popular.

ValidateOnBlur and ValidateOnSubmit could remain in the library for now, but be marked as deprecated, prompting users to swtich to the ...ThenImmediately case to preserve behaviour.

Assuming that you're happy with the design proposed above, I'd be happy to investigate the ValidateOnSubmitOnly case, and hopefully make a PR. The other cases could be left for other contributors (or not implemented at all if there's no demand).

@MangelMaxime
Copy link
Owner

My reasoning for the current implementation is that once the user submitted the form. Then we want to help him fix the errors "as fast as possible".

But I am open for a PR implementing the following cases:

  • ValidateImmediately (trigger validation after every field state change)
  • ValidateOnBlurThenImmediately (currently known as ValidateOnBlur)
  • ValidateOnBlurOnly (trigger only after blur, not while still focused on a field)
  • ValidateOnSubmitThenImmediately (currently known as ValidateOnSubmit)
  • ValidateOnSubmitOnly (trigger only when submitting, not before)

I think these cases are common enough to allow the user to choose between them. For other scenario, like you said people can open an issue to discuss it or fork the project to implement the exact form behaviour they want.

@mattgallagher92
Copy link
Contributor Author

Change to my preferred validation strategy

As you mentioned your reasoning, I thought I'd revisit my reasons. I thought that validating when submitting was the recommendation from Nielsen Norman Group, who I respect for UX design heuristics. However, it seems that they suggest using inline validation (point 1 in their guidelines on reporting errors in forms). Taken with point 7 ("Don’t Validate Fields Before Input is Complete"), it seems to me that what I called ValidateOnBlurOnly would get closest to their guidelines.

Because my new preference is ValidateOnBlurOnly, and the behaviour difference between ValidateOnBlurOnly and ValidateOnBlurThenImmediately is smaller than that between ValidateOnSubmitOnly and ValidateOnSubmitThenImmediately, Fable.Form.Simple's behaviour is closer to what I now want than what I thought I wanted.

Note on implementation difficulties

I looked into this today, but it looks difficult to change this behaviour without also breaking the interface. This is because the error is always recalculated immediately in the current implementation, with the validation strategy simply determining when to first start showing errors. I can't see an obvious way to retain the old error message while the field is being edited.

As mentioned above, I'm more comfortable with Fable.Form.Simple's behaviour than I was before looking into this change. However, I'd still be willing to revisit the investigation into implementing ValidateOnBlurOnly with some pointers/suggestions.

@MangelMaxime
Copy link
Owner

Thank you for the great ressource and indeed, it seems like we don't respect point 7 right now. We either validate too soon (on each key stroke) or too late (on submit).

However, I'd still be willing to revisit the investigation into implementing ValidateOnBlurOnly with some pointers/suggestions.

I don't have a strong pointers to give you. I believe the problem right now is as you discovered we only have single information per field the current value to show.

I suppose the easiest way to fix that would be to update that state not on all keystrokes but based on the validation logic chosen and in what state the form is int. But this means that the view is not anymore totally in sync with the state in memory.

The other way is I think is to store that previous information somewhere, and there are different ideas to explore:

  1. Change the FieldConfig to have both OldValue and CurrentValue (better name to be found)
  2. Have a memory in the DOM or in the FormConfig to store that information
  3. Expose a custom record or object for the user to use in its FormValues. That record would contain the OldValue and CurrentValue.

I think solution 2. is not doable with React because we can't easily store information in the DOM. It can be erased anytime by the rendering process.

I think solution 3, is probably the cleanest and would open the path for more complex forms/fields like Steps supports.

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

No branches or pull requests

2 participants