Why setCustomValidity() not working in React app?

10,419

Solution 1

setCustomValidity doesn't immediately trigger validation, you have to have a form submit event to trigger it or call checkValidity. I've updated your CodePen to show how you can achieve this in React, and it is also included below.

class Form extends React.Component {
  
  onChange(e) {
    let date = new Date(Date.parse(e.target.value));
    
    if (date > new Date()) {
      e.target.setCustomValidity("Please select a date in the past."); 
    } else {
      e.target.setCustomValidity("");
    }
  }
    
  render() {
    return (
      <div>
        <form>
          <input
            id="input"
            type="datetime-local"
            onChange={this.onChange}
          />
          <button type="submit">Submit</button>
        </form>
      </div>
    );
  }
}

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

Solution 2

Hello here is how you need to do it.

import * as React from "react";

export default function Form () {
  const nameInput = React.useRef<HTMLInputElement>(null);
  const [nameVal,setNameVal] = React.useState("");

  const onSubmitHandler = (e: React.FormEvent<HTMLFormElement>) => {
   // handle yow submition
  }

  const onNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (!nameInput.current) return;

    setNameVal(e.currentTarget.value);
    const {validity} = nameInput.current;

    if (nameInput.current.validity.badInput) {
      nameInput.current.setCustomValidity("Set the message to show");
    }

    if (nameInput.current.validity.customError) {
      nameInput.current.setCustomValidity("Set the message to show");
    }

    if (validity.patternMismatch) {
      nameInput.current.setCustomValidity("Set the message to show");
    }

    if (validity.rangeOverflow) {
      nameInput.current.setCustomValidity("Set the message to show");
    }

    if (nameInput.current.validity.rangeUnderflow) {
      nameInput.current.setCustomValidity("Set the message to show");
    }

    if (validity.stepMismatch) {
      nameInput.current.setCustomValidity("Set the message to show");
    }

    if (validity.tooLong) {
      nameInput.current.setCustomValidity("Set the message to show");
    }

    if (validity.tooShort) {
      nameInput.current.setCustomValidity("Set the message to show");
    }

    if (validity.typeMismatch) {
      nameInput.current.setCustomValidity("Set the message to show");
    }

    if (validity.valid) {
      nameInput.current.setCustomValidity("Set the message to show");
    }

    if (validity.valueMissing) {
      nameInput.current.setCustomValidity("Set the message to show");
    }

  
  }

  return (
    <form onSubmit={onSubmitHandler}>
     <label htmlFor="id-name">Name</label>
     <input 
        ref={nameInput}
        type="text"
        required
        min={5}
        max={15}
        value={nameVal}
        onChange={onNameChange}
      />
      <button type="submit">submit</button>
    </form>
  )
  
}

I mean you dont have to add all of them, just the ones you care about

Share:
10,419

Related videos on Youtube

KATq
Author by

KATq

Yet another wannabe developer

Updated on July 04, 2022

Comments

  • KATq
    KATq almost 2 years

    Why setCustomValidity() doesn't work in React? Am I missing something? With vanillia HTML and JS works fine. Or there is other way to easily make something similiar to setCustomValidity?

    React code:

    class Form extends React.Component {
      formVal(e) {
        e.target.setCustomValidity("Test_1");
      }
      formVal2() {
        let inpt = document.getElementById("input");
        inpt.target.setCustomValidity("TEST_2");
      }
      render() {
        return (
          <div>
            <form>
              <input
                id="input"
                type="datetime-local"
                onBlur={this.formVal}
              />
            </form>
            <button onClick={this.formVal2}>Click </button>
          </div>
        );
      }
    }
    

    CodePen - React

    With no React:

    <form>
      <input type="email" id="mail" name="mail">
      <button onclick="test()">Submit</button>
    </form>
    

    // JS

    var input = document.getElementById("mail");
    function test() {
     input.setCustomValidity("test")
    }
    

    CodePen - no React

  • Aniruddha Shevle
    Aniruddha Shevle over 3 years
    Note that, on Mac, Chrome, Error msg won't be visible if the field is not in the viewport while submitting the form! If the field is visible on the viewport then only we can see the proper message, otherwise, that resp field will be focused but the error msg won't be there!