Don't Disable the Submit Button when the Form is Invalid
EDIT 2023-07-04: This is being posted in retrospect because I'm dumping the things in my Notes app onto my blog. I haven't modified this since the posted date, but wanted to preserve the time that I initially wrote it. This post would be more compelling with some experimental data to back up the claims, but I didn't do that at the time of writing. That would make a great follow-up article, though!
Before I get into this, I want to make clear that, like all things in software engineering and in life, there are no hard rules. Everything depends on the context that you’re working in. It may make sense for you to do the opposite of what I suggest. That’s fine! My thoughts on this are shaped by my own experience for the specific applications I’ve worked on. As always, weigh the options in front of you and choose the best one for your task. All I ask is that you consider these points the next time you feel compelled to disable a submit button.
Developing forms for the web is hard. How difficult could it be to put some text fields on a page, add some validation, and a submit button to press when the user’s done? Well, you’ll have to worry about:
- form validation methods (use a JS library vs. native tools)
- ease of maintenance for future you or other developers
- the different ways your user can interact with each field, and how their input affects other fields
- probably a lot of other things, but this is a long list already
All of which are complex issues in their own right! However, there is one choice that I argue is almost always applicable: when your user hasn’t filled out all fields or has invalid data in them, leave the submit button enabled.
It's not really preventing the user from doing anything meaningful
All of your forms must have comprehensive client-side validation and server-side validation. Doing this in both places is “redundant” and violating DRY (Don’t Repeat Yourself, although IMO this isn’t a great principle to follow dogmatically), but they have their purposes.
Client-side validation is not a way to fully prevent bad data from entering your database. Running code in an environment you don’t control (the browser) prevents you from making that possible. Instead, it should be used to guide your user to enter the right data while providing a clear message on how to fix mistakes. Doing this well is important because the form is the main barrier between your user and what they want to accomplish. If you get it wrong, it could lead the to quit the form altogether!
Server-side validation is the final stop before persisting that data permanently. Since you control the server, you have the final say in what can and can’t go through. Not doing this can have negative consequences for wherever your data gets used after that. Pass that data to an external system? You might violate its data requirements and fail the operation. Use that data for further processing? You have no guarantees that you’re provided the data you need.
Again, this is redundant because the rules are defined (maybe) and enforced in two different places. But, since they must be enforced in both to provide very different functionality, it’s a necessary evil.
Since you’re already doing this in both places, why disable the submit button due to invalidation? Unlike providing client-side validation, disabling the submit button provides no actionable feedback. All your user gets is a grayed-out button. They are left guessing on which field they missed or incorrectly entered data into. This is especially problematic for large forms. If you let them submit, you know that one of the two levels of validation will catch this error and provide feedback.