Clue Mediator

Min and Max length input validation in React

📅February 8, 2022

Today, we will show you how to implement min and max length input validation in React. In the previous article, we explained to you how to create a common input component and reuse it for validation in React.

Checkout more articles on ReactJS

Demo Application

Output - Min and Max length input validation in React - Clue Mediator

Output - Min and Max length input validation in React - Clue Mediator

Min and Max length input validation in React

  1. Create a common Input component
  2. Add Min and Max length validation in the Input component
  3. Use the Input component for validation
  4. Output

1. Create a common Input component

Before starting the example, I will suggest you to refer the previous article to create a common Input component.

Reference: Input validation in React

2. Add Min and Max length validation in the Input component

Let’s extend the functionality for min & max validation in the Input component. Here, we will slightly change the `validationHandler` function and add the min & max validation for the input field.

const validationHandler = (e, props) => {
  if (!props.onValidateFunc) return;

  const { value, name } = e.target;
  let msg = null;

  if (!value && props.isReq) {
    msg = `Please enter ${props.title}.`;
  } else if (value && props.reqType && !getRegExp(props.reqType).test(value)) {
    msg = `Please enter valid ${props.title}.`;
  } else if (props.min && value.length < props.min)
    msg = `${props.title} must be at least ${props.min} characters long.`;
  else if (props.max && value.length > props.max) {
    msg = `${props.title} is more than ${props.max} characters long.`;
  }

  props.onValidateFunc(msg, name);
}

Your full component will look like this.

Input.js

import React, { memo } from 'react';
import PropTypes from 'prop-types';

const getRegExp = (type) => {
  let regx = null;
  switch (type) {
    case 'EMAIL':
      regx = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@(([[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
      break;
    case 'URL':
      regx = /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$/;
      break;
    default:
      break;
  }
  return regx;
}

const validationHandler = (e, props) => {
  if (!props.onValidateFunc) return;

  const { value, name } = e.target;
  let msg = null;

  if (!value && props.isReq) {
    msg = `Please enter ${props.title}.`;
  } else if (value && props.reqType && !getRegExp(props.reqType).test(value)) {
    msg = `Please enter valid ${props.title}.`;
  } else if (props.min && value.length < props.min)
    msg = `${props.title} must be at least ${props.min} characters long.`;
  else if (props.max && value.length > props.max) {
    msg = `${props.title} is more than ${props.max} characters long.`;
  }

  props.onValidateFunc(msg, name);
}

const Input = props => {

  const inputProps = {
    name: props.name,
    type: props.type,
    placeholder: props.placeholder || `Enter ${props.title}`,
    className: props.className,
    value: props.value
  }

  return (
    <div class={props.outerClassName}>
      <label class="form-label">{props.title}</label>
      <input {...inputprops}="" onchange="{e" ==""> props.onChangeFunc(e.target.value, e.target.name, e)}
        onBlur={e => validationHandler(e, props)}
      />
      {props.errorMsg && <span class="text-danger">{props.errorMsg === true ? `Please enter ${props.title}.` : props.errorMsg}</span>}
    </div>
  )
}

Input.defaultProps = {
  type: 'text',
  name: '',
  title: '',
  placeholder: '',
  className: 'form-control form-control-sm',
  outerClassName: 'mb-2',
  value: '',
  onChangeFunc: () => { },
  isReq: null,
  reqType: '',
  onValidateFunc: () => { }
}

Input.propTypes = {
  type: PropTypes.string,
  name: PropTypes.string,
  title: PropTypes.string,
  placeholder: PropTypes.string,
  className: PropTypes.string,
  outerClassName: PropTypes.string,
  value: PropTypes.any,
  min: PropTypes.number,
  max: PropTypes.number,
  onChangeFunc: PropTypes.func,
  isReq: PropTypes.bool,
  reqType: PropTypes.string,
  errorMsg: PropTypes.any,
  onValidateFunc: PropTypes.func
}

export default memo(Input);

3. Use the Input component for validation

Now, we will use the common Input component for validation. We will take a `userId` and `ticketNumber` to add the validation of the min & max length.

const [form, setForm] = useState({
  userId: '',
  ticketNumber: ''
});

const onInputValidate = (value, name) => {
  setError(prev => ({
    ...prev,
    [name]: { ...prev[name], errorMsg: value }
  }));
}

const [error, setError] = useState({
  userId: {
    isReq: true,
    errorMsg: '',
    onValidateFunc: onInputValidate
  },
  ticketNumber: {
    isReq: true,
    errorMsg: '',
    onValidateFunc: onInputValidate
  }
});

Let’s render an HTML code for these two fields where we will set a minimum 6 digit and maximum 8 digit validation for User Id and Ticket Number respectively.

<input type="number" name="userId" title="User Id" value={form.userId} min={6} onchangefunc={onInputChange} {...error.userid}="">
<input type="number" name="ticketNumber" title="Ticket Number" value={form.ticketNumber} max={8} onchangefunc={onInputChange} {...error.ticketnumber}="">

Let’s put all things together and see how it looks.

App.js

import React, { useState, useCallback } from 'react';
import Input from './Input';

function App() {

  const [form, setForm] = useState({
    userId: '',
    ticketNumber: ''
  });

  const onInputValidate = (value, name) => {
    setError(prev => ({
      ...prev,
      [name]: { ...prev[name], errorMsg: value }
    }));
  }

  const [error, setError] = useState({
    userId: {
      isReq: true,
      errorMsg: '',
      onValidateFunc: onInputValidate
    },
    ticketNumber: {
      isReq: true,
      errorMsg: '',
      onValidateFunc: onInputValidate
    }
  });

  const onInputChange = useCallback((value, name) => {
    setForm(prev => ({
      ...prev,
      [name]: value
    }));
  }, []);

  const validateForm = () => {
    let isInvalid = false;
    Object.keys(error).forEach(x => {
      const errObj = error[x];
      if (errObj.errorMsg) {
        isInvalid = true;
      } else if (errObj.isReq && !form[x]) {
        isInvalid = true;
        onInputValidate(true, x);
      }
    });
    return !isInvalid;
  }

  const handleSubmit = () => {
    const isValid = validateForm();
    if (!isValid) {
      console.error('Invalid Form!');
      return false;
    }

    console.log('Data:', form);
  }

  return (
    <div class="app">
      <div class="mb-3"><strong>Min & Max Input validation in React - <a href="https://www.cluemediator.com" target="_blank" rel="noreferrer noopener">Clue Mediator</a></strong></div>
      <div class="form">
        <input type="number" name="userId" title="User Id" value={form.userId} min={6} onchangefunc={onInputChange} {...error.userid}="">
        <input type="number" name="ticketNumber" title="Ticket Number" value={form.ticketNumber} max={8} onchangefunc={onInputChange} {...error.ticketnumber}="">
        <button class="btn btn-primary btn-sm mt-2" onclick={handleSubmit}>
          Submit
        </button>
      </div>
    </div>
  );
}

export default App;

4. Output

Run the application and check the output in the browser.

That’s it for today.
Thank you for reading. Happy Coding..!! 🙂

Demo & Source Code

GitHub Repository StackBlitz Project