Form recipe: Conditionally disabling the Submit button

28 Nov 2016

You now know about the differences between the controlled vs. uncontrolled form inputs.

You know that controlled inputs are way more powerful and allow to provide a better user experience.

So you made yourself a couple of forms, and it occurred to you:

I know the email and password fields can’t be empty… Wouldn’t it be cool if I could disable the Submit button until the user fills both in?

Indeed it would! And it is a great UI pattern because it allows us to communicate to the user that something isn’t right before they even hit the button.

And with controlled inputs to make it a reality, there isn’t much we need!

Prerequisite: controlled inputs

Having immediate access to fields’ values is crucial for our ability to disable the button. Therefore, the requirement for this recipe is a form with controlled inputs.

The Case: simple sign-up form

Suppose we have a sign-up form with just two fields, email and password:

Form Recipe: Conditionally disabling the button on jsbin.com

Our goal is to disable the button unless both email and password have something in them.

Instant validation

Recall that with the controlled inputs approach, we store all the input values in the state.

constructor() {
  super();
  this.state = {
    email: '',
    password: '',
  };
}

handleEmailChange = (evt) => this.setState({ email: evt.target.value });
handlePasswordChange = (evt) => this.setState({ password: evt.target.value });

This comes in especially handy for a task like ours because:

  1. We always have the most current values of the inputs.
  2. We can react to any value change immediately.

Typing anything in the input means we end up calling setState with the new value. Or, in other words, that we are re-rendering our form on every key press.

It means we can evaluate a particular condition on every render and do something based on it.

Let’s define the condition for when the button should be disabled: if both email and password are empty.

In code, we could express it like this, right inside render:

const { email, password } = this.state;
const isEnabled =
  email.length > 0 &&
  password.length > 0;

Then, we can simply use this value to pass a disabled prop to the button:

<button disabled={!isEnabled}>Sign up</button>

Voila, the button will now be in a disabled state unless both inputs have something typed in.

Form Recipe: Conditionally disabling the button on jsbin.com

That’s amazingly simple, thanks to controlled inputs.

One more thing

Just when you think you’re done… a caveat pops up!

A form can be submitted by pressing Enter in any text input. Try that right now in the previous JSBin!

We can change the handleSubmit function to check whether the fields are filled:

To avoid repeating the same piece of logic in both handleSubmit and render, let us also extract it into a function of its own.

The changes can be summarized as the following:

canBeSubmitted() {
  const { email, password } = this.state;
  return (
    email.length > 0 &&
    password.length > 0
  );
}

handleSubmit = (evt) => {
  if (!this.canBeSubmitted()) {
    evt.preventDefault();
    return;
  }
  // actual submit logic...
};

render() {
  const isEnabled = this.canBeSubmitted();

  return (
    <form onSubmit={this.handleSubmit}>
      ...
      <button disabled={!isEnabled}>Sign up</button>
      ...
    </form>
  );
}

You can even see it live:

Form Recipe: Conditionally disabling the button on jsbin.com

Gorgeous, right? And really simple!

Going from here

What we’ve got is looking pretty good as is. However, there are opportunities to make it even better.

You can do more complex checks!

You can tweak the canBeSubmitted function to make other assertions. For example, you make sure that the password is longer than six characters, and that email contains a @.

UX

Right now, there also is no indication of which field is the culprit that won’t let the user submit the form. A better UX would be to highlight these inputs in red.

That, however, is an entirely different story for another post… and I can send you an email when a new post on forms comes out if sign up below.

Get a free sample of The Missing Forms Handbook of React

You know how you tear your hair out when your designer asks to make a nice form?

But what if you could implement the form experience your users deserve?

The Missing Forms Handbook of React can help you breeze through your React forms. You will learn how forms fit into the React model. And, you are going to see how to implement common form patterns and structures.

No spam, promise. I hate it as much as you do!

, enjoying the article? Now think of 3 friends who are interested in React, Forms and would be into it, and share the link with them! 👇

https://goshakkk.name/form-recipe-disable-submit-button-react/