Skip to content

btnwtn/form-bureaucracy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Form Bureaucracy

Async form validation.

Installing

$ npm install --save form-bureaucracy

Getting Started

  1. Create a set of Rules.
  2. Use createValidator to create a Rule Validator.
  3. Use the Rule Validator to specify which field to validate against.
  4. Validate some input!

Rules

Rules are functions that accept an input and may return any Truthy value. For example, a Rule to validate some innane requirements for a password would look like this:

const validatePassword = password => {
  const errors = [];

  if (password.length > 16) {
    errors.append("Password can not be secure.");
  }
  if (/[!@#\$%\^&\*\(\)]/.test(password)) {
    errors.append("Password can not contain special characters.");
  }

  return errors;
};

Rules can optionally return a Promise if any asynchronous work is required by the Rule. For example:

const validateEmail = email => {
  return new Promise(resolve => {
    SomeAPI.doesEmailExist(email).then(emailExists => {
      const errors = [];

      if (emailExists) {
        errors.push("Email is already in use!");
      }

      resolve(errors);
    });
  });
};

createValidator

createValidator accepts an Object that maps form inputs to their Validation Rules, and returns a Field Validator function that accepts a field to validate against. For example, given an input email, the createValidator call would like this:

import createValidator from "form-bureaucracy";

const rules = {
  email: email => {
    return [
      email.length === 0 && "Email address is required.",
      !email.includes("@") && `Email address must include an '@' symbol.`
    ];
  }
};

const fieldValidator = createValidator(rules);
const emailValidator = fieldValidator("email");

Field Validator

Field Validators are functions which accept an input, and return a Promise that resolves to an Array of potential errors; they are created by the createValidator function. They are used like any other Promise, e.g.

const emailValidator = fieldValidator("email");

emailValidator("email@example.com").then(errors => {
  if (errors.length) {
    console.log("something is up with this email...");
  }
});

Examples

Basic Field Validation

import createValidator from "form-bureaucracy";

// define a set of rules for form fields to be validated against.
const rules = {
  email: email => {
    return [
      email.length === 0 && "Email address is required.",
      !email.includes("@") && `Email address must include an '@' symbol.`
    ];
  }
};

// create the fieldValidator function
const fieldValidator = createValidator(rules);
const emailValidator = fieldValidator("email");

// validate that field...
emailValidator("email@example.com").then(errors => {
  if (errors.length) {
    return console.log(errors);
  }

  console.log("No errors found.");
});

Asynchronous Rules

You can return a Promise from a Rule if you need to make any API calls or do any asynchronous work.

import createValidator from "form-bureaucracy";

const MockAPI = {
  doesEmailExist: email => {
    // emulate HTTP Request latency
    return new Promise(resolve => setTimeout(resolve(true), 300));
  }
};

const rules = {
  email: input => {
    // Return a Promise instead of an Array.
    return new Promise(resolve => {
      // Make API call to validate the input.
      MockAPI.doesEmailExist(input).then(emailExists => {
        // Resolve with any errors.
        resolve([
          input.length === 0 && "Email address is required.",
          emailExists && "Email address is taken!"
        ]);
      });
    });
  }
};

const fieldValidator = createValidator(rules);
const emailValidator = fieldValidator("email");

// console.log the response
emailValidator("email@example.com").then(console.log);

Usage with React.js

This example does form validation when a field has been blurred.

import React, { Component } from "react";
import createValidator from "form-bureaucracy";

const MockAPI = {
  async doesEmailExist(email) {
    return new Promise(resolve => setTimeout(resolve(true), 300));
  }
};

const rules = {
  async email(input) {
    const emailExists = await MockAPI.doesEmailExist(input);

    return [
      input.length === 0 && "Email is required.",
      emailExists && "That email is already registered!"
    ];
  }
};

const fieldValidator = createValidator(rules);

class Example extends Component {
  state = {
    email: {
      value: "",
      errors: []
    }
  };

  handleChange = event => {
    const { name, value } = event.target;

    this.setState(state => {
      return {
        [name]: {
          ...state[name],
          value
        }
      };
    });
  };

  handleBlur = event => {
    const name = event.target.name;
    const validator = fieldValidator(name);

    validator(this.state[name].value).then(errors => {
      this.setState(state => {
        return {
          [name]: {
            ...state[name],
            errors
          }
        };
      });
    });
  };

  render() {
    return (
      <form style={{ margin: "0 auto", maxWidth: "420px" }}>
        <label>
          Email:
          <input
            type="email"
            name="email"
            value={this.state.email.value}
            onChange={this.handleChange}
            onBlur={this.handleBlur}
          />
        </label>
        {this.state.email.errors.map(error => (
          <p key={error.replace(" ", "-")} style={{ color: "red" }}>{error}</p>
        ))}
      </form>
    );
  }
}

export default Example;

About

Async form validation helpers

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published