Disable and enable button after checking some condition

Viewed 2902

I have this button here

<button className={Classes.Button}
    disabled={!isEnabled}
    type="submit">
        {buttonText}
</button>

which should be disabled or enable after checking the value of some of my inputs. the conditions

const canBeSubmitted = () => {
    return (
      customerData.firstNameState.length > 0 && // TextInput
      customerData.emailState.length > 0 && // TextInput
      customerData.companeyState.length > 0 && // TextInput
      customerData.selected.length > 0 &&   // Dropdown
      customerData.agree === true // checkbox for terms
    );
  };
  let isEnabled = canBeSubmitted();

BTW: The agree checkbox is checked by its handler and works fine. The agree value is false in the state and the handler

 const handleChange = (event) => {
    const field = event.target.id;
    if (field === "firstName") {
      setFirstName({ firstName: event.target.value });
    } else if (field === "email") {
      setEmail({ email: event.target.value });
    } else if (field === "country") {
      setSelected({ country: event.target.value });
    } else if (field === "agree") {
      setAgree(!agree);
      console.log(agree);
    }
  };

but always return false. what am I missing?

Please help me out

2 Answers

If I'm correct, your 'state' isn't changing because of how you're changing 'state variables' in handleChange fat arrow function.

I could be wrong depending on how your 'state' is structured.

I'm assuming your 'state' is structured like this.

const [firstName, setFirstName] = useState("");
const [email, setEmail] = useState("");
const [country, setCountry] = useState("");
const [agree, setAgree] = useState(false);    
  1. Fix your handleChange function.
// Commented out your possibly erroneous code.
const handleChange = (event) => {
    const field = event.target.id;

    if (field === "firstName") {
        // Fix here.
        // setFirstName({ firstName: event.target.value }); ❌
        setFirstName(event.target.value); ✅
    } else if (field === "email") {
        // Fix here.
        // setEmail({ email: event.target.value }); ❌
        setEmail(event.target.value); ✅
    } else if (field === "country") {
        // Fix here.
        // setSelected({ country: event.target.value }); ❌
        setCountry(event.target.value); ✅
    } else if (field === "agree") {
        // Fix here.
        // setAgree(!agree); ❌
        setAgree(event.target.checked); ✅
        console.log(agree);
    }
};
  1. You can then perform your validation like this:
const canBeSubmitted = () => {
    return (
    firstName.trim().length && // TextInput
    email.trim().length && // TextInput
    country.trim().length && // Dropdown
    agree // checkbox for terms
    );
};
  1. It appears your also have a typo here for 'countryState':
customerData.companeyState.length > 0 && // TextInput
  1. It looks like there is a full stop after && operator in your code.
customerData.selected.length > 0 &&.   // Dropdown

Addendum

@Harry9345, you can as well get rid of the handleChange completely.

Full source code below. Demo: https://codesandbox.io/s/crimson-fog-vp19s?file=/src/App.js

import { useEffect, useState } from "react";

export default function App() {
  const [firstName, setFirstName] = useState("");
  const [email, setEmail] = useState("");
  const [country, setCountry] = useState("");
  const [agree, setAgree] = useState(false);

  const canBeSubmitted = () => {
    const isValid =
      firstName.trim().length && // TextInput
      email.trim().length && // TextInput
      country.trim().length && // Dropdown
      agree; // checkbox for terms

    if (isValid) {
      document.getElementById("submitButton").removeAttribute("disabled");
    } else {
      document.getElementById("submitButton").setAttribute("disabled", true);
    }
    console.log({ firstName, email, country, agree });
  };

  useEffect(() => canBeSubmitted());

  return (
    <div>
      <form action="" method="post" id="form">
        <label htmlFor="firstName">First name:</label>
        <br />
        <input
          type="text"
          id="firstName"
          name="firstName"
          value={firstName}
          onChange={(e) => setFirstName(e.target.value)}
        />
        <br />
        <label htmlFor="email">Email Address:</label>
        <br />
        <input
          type="email"
          id="email"
          name="email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
        />
        <br />
        <label htmlFor="country">Choose a country:</label>
        <br />
        <select
          id="country"
          name="country"
          value={country}
          onChange={(e) => setCountry(e.target.value)}
        >
          <option value="">Select..</option>
          <option value="1">USA</option>
          <option value="2">Canada</option>
          <option value="3">Algeria</option>
        </select>
        <br />
        <input
          type="checkbox"
          name="agree"
          id="agree"
          onClick={(e) => setAgree(e.target.checked)}
        />
        <label> I agree.</label>
        <br />
        <button type="submit" id="submitButton">
          Submit
        </button>
      </form>
    </div>
  );
}

You should use state instead of variable:

I added some example:

import { useState } from "react";

const App = () => {
  const [isDisabled, setIsDisabled] = useState(true);
  const [checked, setChecked] = useState(false);

  const canBeSubmitted = () => {
    return checked ? setIsDisabled(true) : setIsDisabled(false);
  };

  const onCheckboxClick = () => {
    setChecked(!checked);
    return canBeSubmitted();
  };

  return (
    <div className="App">
      <input type="checkbox" onClick={onCheckboxClick} />
      <button type="submit" disabled={isDisabled}>
        Submit
      </button>
    </div>
  );
};

export default App;

codesandbox

Of course it's just a sample of code and not very efficient.

Related