Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why setCustomValidity() not working in React app?

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

like image 441
KATq Avatar asked Jul 14 '17 11:07

KATq


3 Answers

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>
like image 126
Paul Avatar answered Nov 15 '22 12:11

Paul


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 (validity.badInput) {
      nameInput.current.setCustomValidity("Set the message to show");
    }

    if (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 (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
        id="id-name"
        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

like image 2
Ernesto Avatar answered Nov 15 '22 12:11

Ernesto


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

like image 2
Wings Avatar answered Nov 15 '22 12:11

Wings