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

[Bug]: isFormValid displays valid form when fields are required but haven't been entered #158

Closed
2 of 4 tasks
ZipBrandon opened this issue Aug 21, 2022 · 2 comments
Closed
2 of 4 tasks
Labels
bug Something isn't working

Comments

@ZipBrandon
Copy link

Which packages are impacted?

  • remix-validated-form
  • @remix-validated-form/with-zod
  • @remix-validated-form/with-yup
  • zod-form-data

What version of these packages are you using?

"@remix-validated-form/with-yup": "2.0.1",
"remix-validated-form": "4.5.5",
"yup": "0.32.11",

Please provide a link to a minimal reproduction of the issue.

https://stackblitz.com/edit/node-uwx1dv?file=app/validated/TestForm.tsx

Steps to Reproduce the Bug or Issue

  1. Go to the sandbox and see that the Submit button is not disabled.
  2. Blur a field without entry and verify submit button is disabled.
  3. Enter text in that field and verify that submit button is enabled even though form is not satisfied.

Expected behavior

I am expecting that the useIsValid() would return that the form is in an invalid state when there is required info that has not been addressed yet.

Screenshots or Videos

No response

Platform

MacOS Chrome Version 104.0.5112.101 (Official Build) (arm64)

Additional context

No response

@ZipBrandon ZipBrandon added the bug Something isn't working label Aug 21, 2022
@airjp73
Copy link
Owner

airjp73 commented Aug 21, 2022

Hi! Thanks for filing an issue.

What you're describing here is the intended behavior. I think there may be room to improve how validation state is tracked to make it more clear, but it an alternate API would still have the same opinions. Other people have brought up related issues before so I'm going to outline these opinions here so I can reference back to it in the future.

Disabling the submit button on a form with no visible errors is bad pattern in terms of UX

It's a very frustrating user experience to fill out a form and find the submit button is still disabled when you're done. If you're a mouse user, it's easy to completely skip an input you think is optional. You never blurred the input, so there are no validation errors being displayed. How are you supposed to know what you need to fix if you can't click the submit button? Users in this situation have to start guessing what's wrong until the submit button is eventually enabled.

The default and preferred pattern of this library is allow the user to click the submit button and then highlight all the validation errors at that point. Just like a normal HTML form, the first invalid input will be focused automatically to direct the user to what they need to correct. This is a much better experience for the user.

Once there are visible errors, it's possible to disable the submit button. The important thing is that the user needs to be able to see the errors. That said, I still don't love that pattern. A user could still not notice an error and clicking the submit button to automatically focus the invalid field is a better experience.

Disabling the submit button breaks progressive enhancement

If supporting users with JS disabled isn't important to you, this won't make a huge difference for you.

If a user has JS disabled, then it's impossible for them to submit a form with a disabled submit button. This isn't just an issue with a clean form. If you disable the submit button when isValid is false, they could run into this situation:

  • User fills out form and submits
  • The backend validates and returns validation errors
  • Now the submit button is disabled and the user is stuck 😬

You can, of course, work around this by using useHydrated from remix-utils.

We track validation errors differently

The way we track the validation errors reflects this opinion. This library differs a bit from other common form libraries in that we don't validate anything until you call validate (normally this is done automatically through getInputProps) or until the user submits the form. So an untouched form has no validation errors (fieldErrors is empty and isValid is true). Coming from other libraries, you might be expecting the errors to be there all the time, but you don't display them because touched is false. In our case, touched is completely optional -- if there's an error present at all, it should be displayed.

Other solutions

Maybe you have a case where disabling the submit button might make sense. One I can think of is if there's only one input in the whole form and it's clearly required. This is a common pattern among form builder services. In that case you could track the input value using useControlField, or you could call validate when the form mounts and change the validationBehavior of the field to "onChange" (you might also need to use the touched state of the field in that case).

But really, even in that situation, does the submit button really need to be disabled? Personally, I think having it enabled all the time is the easiest solution.

@airjp73 airjp73 closed this as completed Aug 21, 2022
@ZipBrandon
Copy link
Author

Thanks for your abundance of information! I do understand this is a sticky problem. I actually have use-cases for this and since my disabling of the field is only CSS style-related -- one can click on it to reveal the form inputs that require attention.

I am currently trying to implement this in a second form context where I can validate() it on mount but not reveal the UI errors unless they are actually touched. This second form context is only used for the submit button.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants