🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
Book a DemoInstallSign in
Socket

react-simple-form-validator

Package Overview
Dependencies
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-simple-form-validator

Simple React JS library to validate form fields

0.3.0
Source
npm
Version published
Weekly downloads
90
11.11%
Maintainers
1
Weekly downloads
 
Created
Source

React simple form validator

Node.js CI Npm package version Maintenance TypeScript

React simple form validator is a simple library to validate your form fields with React JS or React native. The library is easy to use and is written with typescript.

The library exposes a useValidation hook or a ValidationComponent for class based component.

You can view a demo HERE.

1. Installation

  • Run the following commands :
# with npm
npm install react-simple-form-validator --save

# or with yarn
yarn add react-simple-form-validator

2. Use it in your app

For Functional component:

You will use useValidation hook inside your component like this :

import { useValidation } from 'react-simple-form-validator';

const MyFunction = () => {
  const [email, setEmail] = useState('');
  const [name, setName] = useState('');
  
  const { isFieldInError, getErrorsInField, isFormValid } = useValidation({
    fieldRules: {
      email: { email: true },
      name: { required: true }
    },
    state: { email, name }
  });
  
  return (
    <form>
      <input
            id="email"
            type="text"
            onChange={(e) => setEmail(e.target.value)}
            value={email}
          />
      <input
            id="name"
            type="text"
            onChange={(e) => setName(e.target.value)}
            value={name}
          />
    </form>
  );
}

You need to pass the form field state to the useValidation hook in the state propery like above.

You can also pass custom messages, labels, rules, locale (check the documentation below).

The description of the object returned by the hook is :

Function / VariableOutputBenefits
isFormValidbooleanThis variable indicates if the form is valid and if there are no errors.
isFieldInError(fieldName: string)booleanThis function indicates if a specific field has an error. The field name will match with your form state
getErrorMessages(separator: string, separator = '\n')stringThis method returns the different error messages bound to your form state. The argument is optional, by default the separator is a \n. Under the hood a join method is used.
getErrorsInField(fieldName: string)string[]This method returns the error messages bound to the specified field. The field name will match with your form state. It returns an empty array if no error was bound to the field.
getErrorsForField(fieldName: string)ErrorsThis method returns an Errors object containing 3 properties : fieldName: string, failedRules: string[], and messages: string[].
getFailedRules(){[fieldName: string]: string[]}This methods returns the failed rules of your form state
getFailedRulesInField(fieldName: string)string[]This method returns the failed rules bound to a specific field name.

For class component:

Extend "ValidationComponent" class on a your component :

import React from 'react';
import ValidationComponent from 'react-simple-form-validator';

export default class MyForm extends ValidationComponent {
  ...
}

The ValidationComponent extends the React.Component class.

To ensure form validation you have to call the validate method in a custom component (herited from ValidationComponent)

class ClassForm extends ValidationComponent {
  constructor(props) {
    super(props);

    this.fieldRules = {
      email: { email: true },
      name: { required: true }
    };

    this.state = {
      email: '',
      name: ''
    };
  }

   render() {
    return ( 
        <form>
            <input
              id="email"
              type="email"
              onChange={(e) => this.validate({ email: e.target.value, fieldRules: this.fieldRules })}
              value={this.state.email}
              placeholder="Seize an email"
            />
            <input
              id="name"
              type="text"
              onChange={(e) => this.validate({ name: e.target.value, fieldRules: this.fieldRules })}
              value={this.state.name}
              placeholder="Seize a name"
            />
          <button disabled={!this.isFormValid}>Submit</button>
        </form>
    );
   }

The validate method takes as first argument the new state to validate. For instance if you have to validate an email, pass the email value.

The second argument is your field rules validation. You can omit this argument if you set the validation prop in your component.

Once you have extended ValidationComponent your class component can use one of the below methods :

Method / MemberOutputBenefits
this.validate(newState, fieldRules?)voidThis method ensures form validation within the object passed in argument. First argument is the new state to validate. Second argument is your field rules validation
this.isFormValidbooleanThis member indicates if the form is valid and if there are no errors.
this.isFieldInError(fieldName: string)booleanThis method indicates if a specific field has an error. The field name will match with your React state
this.getErrorMessages(separator: string, separator = '\n')stringThis method returns the different error messages bound to your React state. The argument is optional, by default the separator is a \n. Under the hood a join method is used.
this.getErrorsInField(fieldName: string)string[]This method returns the error messages bound to the specified field. The field name will match with your React state. It returns an empty array if no error was bound to the field.
this.getErrorsForField(fieldName: string)ErrorsThis method returns an Errors object containing 3 properties : fieldName: string, failedRules: string[], and messages: string[].
this.getFailedRules(){[fieldName: string]: string[]}This methods returns the failed rules of your form state
this.getFailedRulesInField(fieldName: string)string[]This method returns the failed rules bound to a specific field name.

Existing rules :

You will find bellow the default rules available in the library defaultRules.ts :

RuleBenefits
numbersCheck if a state variable is a number.
emailCheck if a state variable is an email.
requiredCheck if a state variable is not empty.
dateCheck if a state variable respects the date pattern. Ex: date: 'YYYY-MM-DD'
minlengthCheck if a state variable is greater than minlength.
maxlengthCheck if a state variable is lower than maxlength.
equalPasswordCheck if a state variable is equal to another value (useful for password confirm).
hasNumberCheck if a state variable contains a number.
hasUpperCaseCheck if a state variable contains a upper case letter.
hasLowerCaseCheck if a state variable contains a lower case letter.
hasSpecialCharacterCheck if a state variable contains a special character.

You can also extend these rules with your own custom rules :

  • For function component :
import { defaultRules } from 'react-simple-form-validator';

// extend default rules with my custom any rule
const customRules = { ...defaultRules, any: /^(.*)$/ };

const { isFieldInError, getErrorsInField, isFormValid } = useValidation({
    fieldRules: {
      email: { email: true },
      name: { required: true }
    },
    state: { firstName, lastName, email, civility },
    rules: customRules
  });
  • For class component :
import { defaultRules } from 'react-simple-form-validator';

// extend default rules with my custom any rule
const customRules = { ...defaultRules, any: /^(.*)$/ };

<FormTest rules={customRules} />

// Or override the custom rules into the super class child constructor

// FormTest.js
class FormTest extends ValidationComponent {
  constructor(props) {
    super({...props, rules: { ...defaultRules, any: /^(.*)$/ }});

    this.fieldRules = {
      email: { email: true },
      name: { required: true }
    };
  }
}

Existing messages :

The library also contains a defaultMessages.ts file which includes the errors label for a language locale.

  • For function component :
import { defaultMessages } from 'react-simple-form-validator';

const { isFieldInError, getErrorsInField, isFormValid } = useValidation({
  fieldRules: {
    email: { email: true },
    name: { required: true }
  },
  state: { email, name },
  messages: {
    en: {...defaultMessages.en, numbers: "error on numbers !"},
    fr: {...defaultMessages.fr,numbers: "erreur sur les nombres !"}
  }
});
  • For class component :

You can override the messages component React props :

import { defaultMessages } from 'react-simple-form-validator';

const messages = {
  en: {...defaultMessages.en, numbers: "error on numbers !"},
  fr: {...defaultMessages.fr,numbers: "erreur sur les nombres !"}
};

<FormTest messages={messages} />

Custom labels for error message interpolation :

You can add custom labels, which will be useful if you want to change the error messages label or translate it to the local language :

  • For function component :
import { defaultMessages } from 'react-simple-form-validator';

const { isFieldInError, getErrorsInField, isFormValid } = useValidation({
  fieldRules: {
    email: { email: true },
    name: { required: true }
  },
  state: { email, name },
  labels: {
    name: 'Name',
    email: 'E-mail',
    number: 'Phone number'
  }
});
  • For class component :
const labels = {
  name: 'Name',
  email: 'E-mail',
  number: 'Phone number'
};

<FormTest labels={labels} />

// Or override the custom labels into the super class child constructor

// FormTest.js
class FormTest extends ValidationComponent {
  constructor(props) {
    const labels = {
      name: 'Name',
      email: 'E-mail',
      number: 'Phone number'
    };
    super({...props, labels});

    this.fieldRules = {
      email: { email: true },
      name: { required: true }
    };
  }
}

Specify language locale :

You can specify the default custom local language :

  • For function component :
const { isFieldInError, getErrorsInField, isFormValid } = useValidation({
  fieldRules: {
    email: { email: true },
    name: { required: true }
  },
  state: { email, name },
  locale: 'fr'
});
  • For class component :
<FormTest locale="fr" />

// Or override the custom locale into the super class child constructor

// FormTest.js
class FormTest extends ValidationComponent {
  constructor(props) {
    super({...props, locale: 'fr'});

    this.fieldRules = {
      email: { email: true },
      name: { required: true }
    };
  }
}

3. Complete example

You can find a concrete Functional component example on FunctionForm.tsx (Typescript) :

Function Component:

import React, { Fragment, FunctionComponent, useState } from 'react';
import { defaultMessages, defaultRules, FieldsToValidate, useValidation } from 'react-simple-form-validator';

interface FunctionFormProps {
  validation: FieldsToValidate;
}

const FunctionForm: FunctionComponent<FunctionFormProps> = (props) => {
  const [touchedFields, setTouchedFields] = useState({
    civility: false,
    email: false,
    firstName: false,
    lastName: false
  });
  const [email, setEmail] = useState('');
  const [firstName, setFirstName] = useState('');
  const [lastName, setLastName] = useState('');
  const [civility, setCivility] = useState('');

  const { isFieldInError, getErrorsInField, isFormValid } = useValidation({
    fieldsRules: props.validation,
    state: { firstName, lastName, email, civility },
    rules: { ...defaultRules, customCivilityRule: /^(Mrs|Ms|Miss)$/ },
    messages: {
      ...defaultMessages,
      en: { ...defaultMessages['en'], customCivilityRule: 'Civility is incorrect (Mrs/Ms/Miss)' }
    }
  });

  const onBlurHandler = (event: React.FormEvent<HTMLElement>, field: string) =>
    setTouchedFields((prevFields) => ({ ...prevFields, [field]: true }));

  const formSubmitHandler = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    console.log('Form values : ', civility, email, firstName, lastName);
    setFirstName('');
    setLastName('');
    setEmail('');
    setCivility('');
    setTouchedFields({ firstName: false, lastName: false, email: false, civility: false });
  };

  return (
    <Fragment>
      <h2>Functional Form</h2>
      <form onSubmit={formSubmitHandler}>
        <div className="form-control">
          <label htmlFor="gender">Civility</label>
          <input
            id="civility"
            type="text"
            onChange={(e) => setCivility(e.target.value)}
            onBlur={(e) => onBlurHandler(e, 'civility')}
            value={civility}
            placeholder="Seize a civility (Mrs or Ms or Miss)"
          />
          <p className="error-text">
            {touchedFields.civility && isFieldInError('civility') && getErrorsInField('civility').join('\n')}
          </p>
        </div>
        <div className="form-control">
          <label htmlFor="email">Email</label>
          <input
            id="email"
            type="email"
            onChange={(e) => setEmail(e.target.value)}
            onBlur={(e) => onBlurHandler(e, 'email')}
            value={email}
            placeholder="Seize an email"
          />
          <p className="error-text">
            {touchedFields.email && isFieldInError('email') && getErrorsInField('email').join('\n')}
          </p>
        </div>
        <div className="form-control">
          <label htmlFor="firstName">First name</label>
          <input
            id="firstName"
            type="text"
            onChange={(e) => setFirstName(e.target.value)}
            onBlur={(e) => onBlurHandler(e, 'firstName')}
            value={firstName}
            placeholder="Seize a first name"
          />
          <p className="error-text">
            {touchedFields.firstName && isFieldInError('firstName') && getErrorsInField('firstName').join('\n')}
          </p>
        </div>
        <div className="form-control">
          <label htmlFor="astName">Last Name</label>
          <input
            id="lastName"
            type="text"
            onChange={(e) => setLastName(e.target.value)}
            onBlur={(e) => onBlurHandler(e, 'lastName')}
            value={lastName}
            placeholder="Seize a last name"
          />
          <p className="error-text">
            {touchedFields.lastName && isFieldInError('lastName') && getErrorsInField('lastName').join('\n')}
          </p>
        </div>
        <div className="actions">
          <button disabled={!isFormValid}>Submit</button>
        </div>
      </form>
    </Fragment>
  );
};

export default FunctionForm;

Class component:

You can find a concrete Class component example on ClassForm.tsx (Typescript) :

import ValidationComponent, { ClassValidationProps, FormState } from 'react-simple-form-validator';
import { Fragment } from 'react';

class ClassForm extends ValidationComponent<ClassValidationProps, FormState> {
  constructor(props: ClassValidationProps) {
    super(props);

    this.state = {
      civility: '',
      email: '',
      firstName: '',
      lastName: '',
      touchedFields: { civility: false, firstName: false, lastName: false, email: false }
    };
  }

  onBlurHandler(event: React.FormEvent<HTMLElement>, field: string): void {
    this.setState({ touchedFields: { ...this.state.touchedFields, [field]: true } });
  }

  formSubmitHandler(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();

    const { civility, email, firstName, lastName } = this.state;

    console.log('Form Values : ', civility, email, firstName, lastName);

    this.setState({
      civility: '',
      email: '',
      firstName: '',
      lastName: '',
      touchedFields: { civility: false, firstName: false, lastName: false, email: false }
    });
  }

  render(): JSX.Element {
    return (
      <Fragment>
        <h2>Class based Form</h2>
        <form onSubmit={this.formSubmitHandler.bind(this)}>
          <div className="form-control">
            <label htmlFor="gender">Civility</label>
            <input
              id="civility"
              type="text"
              onChange={(e) => this.validate({ civility: e.target.value })}
              onBlur={(e) => this.onBlurHandler(e, 'civility')}
              value={this.state.civility}
              placeholder="Seize a civility (Mrs or Ms or Miss)"
            />
            <p className="error-text">
              {this.state.touchedFields.civility &&
                this.isFieldInError('civility') &&
                this.getErrorsInField('civility').join('\n')}
            </p>
          </div>
          <div className="form-control">
            <label htmlFor="email">Email</label>
            <input
              id="email"
              type="email"
              onChange={(e) => this.validate({ email: e.target.value })}
              onBlur={(e) => this.onBlurHandler(e, 'email')}
              value={this.state.email}
              placeholder="Seize an email"
            />
            <p className="error-text">
              {this.state.touchedFields.email &&
                this.isFieldInError('email') &&
                this.getErrorsInField('email').join('\n')}
            </p>
          </div>
          <div className="form-control">
            <label htmlFor="firstName">First name</label>
            <input
              id="firstName"
              type="text"
              onChange={(e) => this.validate({ firstName: e.target.value })}
              onBlur={(e) => this.onBlurHandler(e, 'firstName')}
              value={this.state.firstName}
              placeholder="Seize a first name"
            />
            <p className="error-text">
              {this.state.touchedFields.firstName &&
                this.isFieldInError('firstName') &&
                this.getErrorsInField('firstName').join('\n')}
            </p>
          </div>
          <div className="form-control">
            <label htmlFor="astName">Last Name</label>
            <input
              id="lastName"
              type="text"
              onChange={(e) => this.validate({ lastName: e.target.value })}
              onBlur={(e) => this.onBlurHandler(e, 'lastName')}
              value={this.state.lastName}
              placeholder="Seize a last name"
            />
            <p className="error-text">
              {this.state.touchedFields.lastName &&
                this.isFieldInError('lastName') &&
                this.getErrorsInField('lastName').join('\n')}
            </p>
          </div>
          <button disabled={!this.isFormValid}>Submit</button>
        </form>
      </Fragment>
    );
  }
}

export default ClassForm;

4. How to contribute

If you want to contribute to this project and make it better, your help is very welcome. Contributing is also a great way to learn more about social coding on Github, new technologies and and their ecosystems and how to make constructive, helpful bug reports, feature requests and the noblest of all contributions: a good, clean pull request.

Method

  • Create a personal fork of the project on Github.
  • Clone the fork on your local machine.
  • Implement/fix your feature, comment your code.
  • Follow the code style of this project, including indentation.
  • Write or adapt tests as needed.
  • Add or change the documentation as needed.
  • Squash your commits into a single commit with git's interactive rebase. Create a new branch if necessary.
  • Push your branch to your fork on Github, the remote origin.
  • From your fork open a pull request in the correct branch. Target the project's master branch.

Install the project

Run this command to install the library dependencies :

npm install

Build the library :

npm run build 

Launch tests :

# single run
npm run test 

# watch mode
npm run test:watch

Run the React JS example project :

cd examples/react-js && yarn install

Start the example project :

yarn start
  • If you modify the library don't forget to re-run npm run build to apply modifications into the example project.

Keywords

react

FAQs

Package last updated on 16 Dec 2021

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts