Why setCustomValidity() not working in React app?

Viewed 12483

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

4 Answers

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

In case you want to show validation for required fields that are left empty you should set setCustomValidity on onInvalid like this:

<input onInvalid={e => e.target.setCustomValidity('Your custom message')} />

And if you are using typescript like this:

<input onInvalid={e => (e.target as HTMLInputElement).setCustomValidity('Enter User Name Here')} />

In case you are want to handle validation for values you can add it like here: https://stackoverflow.com/a/45695707/6912349

Short answer:

<input required onInvalid={(e)=>{e.target.setCustomValidity('Your custom validation message here')}} />
Related