Home > Software design >  Check if html input tag is required
Check if html input tag is required

Time:10-06

In my react js application i have the next input:

  <input required type="text" id="fname" name="fname" value=""/>

In the case above if the form will be submitted the without input value the will appear a message: Please fill in this field, because it is required. Instead of this text i want to add a custom html element with a different content and style.
I want to check after the form is submitted that this input is required and there is no value. So if there is that scenario then to show a custom element bellow like: <div>No data here</div>
I need to achieve this without using the form tag just to create a custom input component in React js and to do something like:

export default function Input() {
  const ref = React.useRef();

  return (
    <div className="App">
       <input ref={ref} required type="text" id="fname" name="fname" value=""/>
       {ref.current.isError ? <div>Message</div> : null}
    </div>
  );
}

Is this possible to check?

CodePudding user response:

You can use onInvalid method on input e.g:

function Input() {
  const [invalid, setInvalid] = useState<boolean>(false);
  const onSubmit = (data: any) => {
    setInvalid(false);
    console.log(data)
  }

  return (
    <div style={{ margin: '60px'}}>
      <form onSubmit={onSubmit}>
        <input
          id="fname"
          name="fname"
          required
          type="text"
          onInvalid={(e) => {
            e.preventDefault();
            // if you have ref you can obtain reason why this input is invalid
            // console.log(ref.current?.validity.valueMissing);
            // or just use e.target.validity
            setInvalid(true);
          }}
        />
        <button type="submit">submit</button>
      </form>
      {invalid && "invalid"}
    </div>
  );
}

useState is used here to cause re-render component

Edit: if you don't want to have form inside Input component then just move state to parent component e.g:

function Input(props: { invalid: boolean; setInvalid: () => void }) {
  const { invalid, setInvalid } = props;

  return (
    <div style={{ margin: '60px'}}>
      <input
        id="fname"
        name="fname"
        required
        type="text"
        onInvalid={(e) => {
          e.preventDefault();
          setInvalid();
        }}
      />
      {invalid && "invalid"}
    </div>
  );
}

function App() {
  const [invalid, setInvalid] = useState<Record<string, boolean>>({});

  const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
    setInvalid({});
    console.log(event);
  }

  return (
    <div className="App">
      <form onSubmit={handleSubmit}>
        <Input invalid={invalid.fname} setInvalid={() => setInvalid(state => ({...state, fname: true}))}/>
        <button type="submit">submit</button>
      </form>
    </div>
  );
}

CodePudding user response:

  • All you need is to check if the input is empty or not and based on result we are making a decision for printing message.
  • All we need is useState hook, onSubmit form validation.

index.js

import React from "react";
import ReactDOM from "react-dom";
import MyInput from "./MyInput.js";
class App extends React.Component {
  render() {
    return (
      <div>
       // validate attribute to defind which validation we need
        <MyInput validate="email" />
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("container"));

MyInput.js

import React, { useState } from "react";
const MyInput = ({ validate }) => {
  const [userInput, setUserInput] = useState("");
  const [isError, setIsError] = useState(false);
  const [errorMessage, setErrorMessage] = useState("");
  const handleInput = (e) => {
    setUserInput(e.target.value);
    setIsError(false);
  };
  function validateEmail(email) {
    var re = /\S @\S \.\S /;
    return re.test(email);
  }
//you can defind more states such as for password or as per your requirement.
  const validateField = (fieldType) => {
    switch (fieldType) {
      case "email":
        if (validateEmail(userInput)) {
          setIsError(false);
        } else {
          setErrorMessage("Need proper email..");
          setIsError(true);
        }
        break;
      default:
        setIsError(false);
    }
  };
  const handleSubmit = (e) => {
    e.preventDefault();
    validateField(validate);
  };
  return (
    <form onSubmit={handleSubmit}>
      <input type="text" value={userInput} onChange={handleInput} />
      {isError ? <p>{errorMessage}</p> : ""}
      <input type="submit" />
    </form>
  );
};

export default MyInput;

Here is working example.

<iframe src="https://codesandbox.io/embed/react-playground-forked-ozgle5?fontsize=14&hidenavigation=1&theme=dark&view=preview" style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;" title="React PlayGround (forked)" allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking"
  sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"></iframe>

  • Related