Skip to content

Kallenju/simpower-validation

Repository files navigation

simpower-validation

Modern, simple but powerful form validation library written in pure JavaScript, with no dependencies.

This is the right choice for you if you have a website or landing page without frameworks.

The library is very simple. There are no complicated predefined rules here because there are many npm packages that provide these rules. It only can checks the rules and inserts the error or success message into the container, which can be found in the current HTML using the querySelector method, or dynamically created and inserted into the HTML. The library also has many callbacks, such as on successful validation of the entire form or on failure of a field validation.

Features

  • small size and zero dependencies
  • custom rules
  • custom messages
  • custom styles and css classes for valid/invalid fields and success/error messages
  • custom places for the messages

Installation

npm

npm i simpower-validation

Then it can be used as an imported module with module bundlers:

import SimpowerValidation from 'simpower-validation';

const validate = new SimpowerValidation('#form');

If you don't use module bundlers, you can import SimpowerValidation via a browser:

import SimpowerValidation from '[relative or absolute path to node_modules folder]/simpower-validation/simpower-validation.esm.js';

const validate = new SimpowerValidation('#form');

Or you can just include SimpowerValidation script on your page from CDN and call it as window.SimpowerValidation:

<script src="https://cdn.jsdelivr.net/npm/simpower-validation/simpower-validation.production.min.js"></script>

<script>
  window.addEventListener('DOMContentLoaded', () => {
    const validate = new window.SimpowerValidation('#form');
  });
</script>

Quick start

Let's say we have a basic HTML layout:

<form id="form">
  <label for="name">Enter your name</label>
  <input id="name" name="name" type="text" placeholder="Enter your name" />
  <label for="email">Enter your email</label>
  <input id="email" name="email" type="email" placeholder="Enter your email" />
  <button type="submit">Submit</button>
</form>

Next, let's add SimpowerValidation to the layout and define some rules.

First, we must create an instance new SimpowerValidation('#form') by passing a form selector, or the element as an argument.

Second, we must call .addField() with the field selector, or DOM element, or field name attribute as the first argument and the rules array as the second argument.

const validation = new SimpowerValidation('#form');

validation
  .addField('name', [
    {
      validator(inputValue) {
        return inputValue.trim();
      },
      errorMessage: 'Name is required',
    },
    {
      validator(inputValue) {
        const nameRegEx = /^[a-zA-Z]{1,40}$/;
        return inputValue.match(nameRegEx);
      },
      errorMessage: 'Name is invalid',
    },
  ])
  .addField('email', [
    {
      validator(inputValue) {
        if (!inputValue.trim()) {
          return true
        }

        const emailRegEx = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;

        return inputValue.match(emailRegEx);
      },
      errorMessage: 'Email is invalid'
    },
  ]);

That's all! The form is now validated!

See the current example.

Let's consider API.

API

Instance setting

const validation = new SimpowerValidation(parentElement: string | Element[, globalConfig: object]);

Example of the full setting:

Let's change the HTML layout mentioned above:

<form id="form">
  <label for="name">Enter your name</label>
  <input id="name" name="name" type="text" placeholder="Enter your name" />
  <label for="email">Enter your email</label>
  <input id="email" name="email" type="email" placeholder="Enter your email" />
  <button type="submit">Submit</button>
</form>

<div id="messagesContainerForAllInputs"></div>

<div id="messageContainerForEmailInput"></div>
const validation = new SimpowerValidation(
  '#form',
  {
    validateFieldOnEvent: {
      event: 'blur',

      afterFirstSubmition: true,

      lockInputOnValidation: false,

      fieldValueHandler(fieldValue) {
        return fieldValue;
      },

      ruleErrorMessages: {
        on: true,
        position: {
          append: '#messagesContainerForAllInputs',
        },
        removeContainerFromDOMAfterSuccess: true,
        classes: ['message-css-class', 'error-message-css-class'],
      },

     successfulValidationMessage: {
        on: true,
        successMessage: 'Validation succeeded',
        position: {
          append: '#messagesContainerForAllInputs',
        },
        removeContainerFromDOMAfterFail: true,
        classes: ['message', 'message_success'],
      },

      invalidViewOfField: {
        on: true,
        classes: ['input_view_invalid'],
      },

      validViewOfField: {
        on: true,
        classes: ['input_view_valid'],
      },
    },

    validateOnSubmit: {
      lockFormOnValidation: false,
      revalidateAllFieldsBeforeSubmition: false,
    },
  },
)
validateFieldOnEvent
Field Description Type
event JavaScript Event. tdis event is added to form elements tdat have been added for validation. When tde event fires, validation starts. If tde event name is invalid, unvalidated elements will be validated when attempting to submit. string
afterFirstSubmition If true, validation after the event specified in the 'event' parameter will work only after the first submission attempt. boolean
lockInputOnValidation This option is useful if an asynchronous validator is specified. It sets the disabled attribute on the fields for the duration of the validation. boolean
fieldValueHandler If exists, this function change value which take validator functin. It is very useful feature if you, for example, use masks for inputs (you can use `fieldValueHandler`for unmasking of input value before validation. function
ruleErrorMessages.on Enable error message boolean
ruleErrorMessages.position Define where error message will be inserted. It has four optional properties: 'append', 'prepand', 'after' and 'before'. Possible value type is string | Element. object
ruleErrorMessages.
  removeContainerFromDOMAfterSuccess
If true, a error message will be deleted after a successful validation. boolean
ruleErrorMessages.classes ССS classes to be added to containers with error messages. Array with css classes
successedValidationMessage.on Enable success messages boolean
successedValidationMessage.on Text of success messages string
successedValidationMessage.position Define where success message will be inserted. It has four optional properties: 'append', 'prepand', 'after' and 'before'. Possible value type is string | Element. object
successedValidationMessage.
  removeContainerFromDOMAfterFail
If true, a success message will be deleted after a failed validation. boolean
successedValidationMessage.classes ССS classes to be added to containers with success messages. Array witd css classes
invalidViewOfField.on Enable invalid views of fields boolean
invalidViewOfField.classes ССS classes to be added to invalid fields. Array witd css classes
validViewOfField.on Enable valid views of fields/td> boolean
validViewOfField.classes ССS classes to be added to valid fields. Array witd css classes
validateOnSubmit
Field Description Type
lockFormOnValidation This option is useful if an asynchronous validator is specified. It sets the disabled attribute for all form elements. boolean
revalidateAllFieldsBeforeSubmition Enables forced validation of all fields before submission, even those that have already been validated. boolean

validation.addField(field: string | Element, rules: Array[, config: object]): validation

The first argument is the field selector, or DOM element, or field name attribute. The second argument is the rules array. The third argument contain local config for field. The argument is structurally identical to validateFieldOnEvent object in the global config.

rule.

Example of the full setting:

{
  validator(value) {
    return value.toString().trim()
  },

  errorMessage: 'The field is required'
}

In this example validator method return boolean. In case false, then value of errorMessage will be inserted in error message container, if showing of error messages is enabled.

There is the other variant of rule object:

{
  validator(value) {
    if (typeof value !== 'string') {
      return {
        result: false,
        errorMessage: 'The value must be of type "string".'
      }
    } else if (!value.trim()) {
      return {
        result: false,
        errorMessage: 'The value must not be of type "number".'
      }
    }

    return true;
  },
}

validator method can return an object with an error message, the text content of which depends on various conditions.

config.

The argument is structurally identical to validateFieldOnEvent object in the global config.

The third argument overrides the corresponding properties in the global configuration for the specific field.

So, for example, if we set the following setting for the email field in the example above, the name field will be validated after the blur event, while the email field will be validated after the input event. Also it changes container for error or successful messages.

{
  event: 'input',

  ruleErrorMessages: {
    position: {
      append: '#messageContainerForEmailInput',
    },
  },

  successfulValidationMessage: {
    position: {
      append: '#messageContainerForEmailInput',
    },
  },
}

Callbacks

There are four types of callbacks:

  1. when field or form validation starts: validation.onStartValidation(callback: function, eventName: string): validation
  2. when field or form validation ends: validation.onEndValidation(callback: function, eventName: string): validation
  3. when field or form validation succeeded: validation.onSuccess(callback: function, eventName: string): validation
  4. when field or form validation failed: validation.onFail(callback: function, eventName: string): validation

Callbacks have two arguments. The first argument is built-in event object, the second one is the object in case of validation of all fields during submition attemt or a field in case of validation of a field.

The callbacks take two arguments. The first argument is the built-in event object, the second is the object validation.form when submitting, or the object (validation.fields[someFieldId]) in case of validation of a field.

object with a form

Example of the object (validation.form):

{
  elem: <form id="form">...</form>,
  formElements: elem.elements,
  submitting: false,
  isSubmitted:  true,
}

object with a field

Example of the object (validation.fields[someFieldId]):

{
  elem: <input id="email" name="email" type="email" placeholder="Enter your email"/>,
  defaultValue: elem.defaultValue,
  rules: [
    {
      validator(inputValue) {
        if (!inputValue.trim()) {
          return true
        }

        const emailRegEx = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;

        return inputValue.match(emailRegEx);
      }
      errorMessage: 'Email is invalid'
    },
  ]
  eventHandlers: Map(1) {{
    handlerName: 'validateOnFieldInput',
    event: 'input'
  } => validation.validateOnFieldEvent.bind(validation)},
  isValid: false,
  isPotentiallyValid: false,
  wasValidated: false,
  successMessage: null,
  errorMessage: null,
  errorMessageIsShown: false,
  successMessageIsShown: false,
  config: {
    event: 'input'
  },
}