How to restrict end date before start date after selected start date in React.JS or in html input type=date""

4k Views Asked by At

function App() {
  let [account, setAccount] = React.useState({
    startdate: "",
    enddate: "",
    reason: "",
    leavetype: "",
  });

  function handleChange(e) {
    let name = e.target.name;
    let value = e.target.value;
    account[name] = value;
    setAccount(account);
  }
  function Submit(e) {
    e.preventDefault();
    console.log(account);
  }
  return (
    <div>
      <fieldset>
        <form className="" method="post" onSubmit={Submit}>
          Start Date:
          <input
            type="date"
            name="startdate"
            min={new Date().toISOString().split("T")[0]}
            onChange={handleChange}
            required
          />
          End Date:
          <input
            type="date"
            name="enddate"
            // min={}
            onChange={handleChange}
            required
          />
        </form>
      </fieldset>
    </div>
  );
}

ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>

1

There are 1 best solutions below

1
On BEST ANSWER

You need to use the state that you have.

function App() {
  const [account, setAccount] = React.useState({
    startdate: "",
    enddate: "",
    reason: "",
    leavetype: "",
  });

  function handleChange(e) {
    const name = e.target.name;
    const value = e.target.value;
    // treat state as immutable!
    // you need to creaet a new object here
    // See https://stackoverflow.com/a/25333702/17487348 for how to create a property from a string in ES6
    setAccount({...account, [name]: value});
  }
  function Submit(e) {
    e.preventDefault();
    console.log(account);
  }
  return (
    <div>
      <fieldset>
        <form className="" method="post" onSubmit={Submit}>
          <legend>Your trip</legend>
          <label for="startdate">Start Date:</label>
          <input
            type="date"
            name="startdate"
            min={new Date().toISOString().split("T")[0]}
            onChange={handleChange}
            required
          />
          <label for="enddate">End Date:</label>
          <input
            type="date"
            name="enddate"
            disabled={account.startdate === "" ? true: false}
            min={account.startdate ? new Date(account.startdate).toISOString().split("T")[0]: ""}
            onChange={handleChange}
            required
          />
        </form>
      </fieldset>
    </div>
  );
}

ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>

When you look at the code there are some other changes which you should consider. I would disable the end date date picker as long as there is no start date selected or set sensible default values for start end end date (e.g. today for both) and set those when defining the state.

More important: You should treat state as immutable that means you need to create a new object every time the state changes as React only does a shallow comparison. Otherwise the component won't re-render. So use setAccount({...account, [name]: value}); to update your state. You need to use [] here so the variable content is interpreted as the name of the property. See this thread.

You also probably want to use <label> and maybe <legend>. See the MDN docs for <fieldset>.

For more options to control the datepicker see MDN docs for <input type="date">.