Coder Social home page Coder Social logo

hoc-form's Introduction

hoc-form β€’ Travis Coveralls github npm license

Tired of writing custom form validation on every project you might work on? Let’s try hocForm, form validation on React has rarely been so simple! πŸ€—

Requirements

hocForm needs at least [email protected] and [email protected] to work.

Installation

Using npm:

npm install --save hoc-form

yarn add hoc-form works fine too!

Usage

import React from 'react';
import hocForm, { Field } from 'hoc-form';

// First, we need a input component to render our text field
function Input({
  input = {},
  label = '',
  meta = {},
  placeholder = '',
  type = 'text',
}) {
  return (
    <div>
      <label>
        {label}
      </label>
      <input
        placeholder={placeholder}
        type={type}
        {...input}
        onBlur={e => input.onBlur && input.onBlur(e.target.value)}
        onChange={e => input.onChange(e.target.value)}
      />
      {meta.error && <span>{meta.error}</span>}
    </div>
  );
}

// Then, we need to create our form component and its helpers
const unavailableUsernames = [
  'elonmusk',
  'ironman',
  'lukeskywalker',
];

function validateLogin(value = '') {
  if (value.trim() === '') {
    return Promise.reject('Please enter an username');
  }

  return unavailableUsernames.includes(value)
    ? Promise.reject('This username is unavailable')
    : Promise.resolve()
}

function validatePassword(value = '') {
  if (value.trim().length < 6) {
    return Promise.reject('Password must contain 6 characters or more');
  }

  return Promise.resolve();
}

function Form({ onSubmit }) {
  return (
    <form onSubmit={onSubmit} noValidate>
      <Field
        name="login"
        component={Input}
        props={{
          label: 'Login *',
          onBlur: value => validateLogin(value),
          placeholder: 'elonmusk',
          type: 'string',
        }}
      />
      <Field
        name="pwd"
        component={Input}
        props={{
          label: 'Password *',
          type: 'password',
        }}
      />
      <button type="submit">Sign up</button>
    </form>
  );
}

// Finally, an export of our wrapped form component
// with a validation function
export default hocForm({
  validate(values, props) {
    let errors = {};
    const errorCatcher = (key, callback, ...args) => (
      callback(values[key], args)
        .catch(error => ({ [key]: error }))
    );

    return Promise.all([
      errorCatcher('login', validateLogin),
      errorCatcher('pwd', validatePassword),
    ]).then((errors) => {
      const results = errors.reduce((acc, item) => ({ ...acc, ...item }), {});
      return Object.keys(results).length ? Promise.reject(results) : Promise.resolve();
    });
  }
})(Form);

Please check out the complete demo! πŸš€

API

hocForm({ options })(MyFormComponent) => React.Component

Renders your MyFormComponent contexted with hocForm.

Two arguments are required:

  • An options object to define the validate function and optional initialValues
  • A form React.Component to render.

options.validate(values, props) => Promise

Validates the form on submit.

Arguments:

  1. values (Object): An object containing all fields keys and their value.
  2. props (Object): An object containing all props provided to MyFormComponent.

Returns:

  • A promise:
    • On success, your must return Promise.resolve()
    • In case of failure, your must return Promise.reject({}). The object parameter must contain every field key with its error (type of string or else, depends on how your components used with Field are designed).

Example, with errors as strings:

function validate(values, props) {
  let errors = {};

  if (values.username) {
    if (!props.isUsernameAvailable(values.username)) {
      errors = { ...errors, username: 'This username is unavailable' };
    }
  } else {
    errors = { ...errors, username: 'Please enter an username' };
  }

  if (!values.password) {
    errors = { ...errors, password: 'Please enter a password' };
  }

  return Object.keys(errors).length
    ? Promise.reject(errors)
    : Promise.resolve();
}

options.initialValues: Object

Object containing all initial values following fields keys.

Example:

initialValues: {
  country: 'United Kingdom',
  phone: '+44',
}

MyFormComponent: React.Component

A React.Component rendering a form including some hocForm.Field items.

Example:

function Form({ onSubmit }) {
  return (
    <form onSubmit={onSubmit} noValidate>
      <Field
        name="login"
        component={Input}
        props={{
          label: 'Login *',
          type: 'string',
        }}
      />
    />
  );
}

Please check out a complete example here.

Field({ options }) => React.Component

Renders a form field, contexted with hocForm.

options.name: String

The name used in your options.validate function.

Example:

<Field
  name="login"
/>

options.component: React.Component

The React.Component rendered by Field.

Example:

<Field
  component={Input}
/>

options.props: Object

The properties provided to the component parameter.

Example:

<Field
  props={{
    label: 'Login *',
    onBlur: (value, otherValues) => Promise.resolve(),
    placeholder: 'elonmusk',
    type: 'string',
  }}
/>

Please check out a complete example here.

Which extra-props my components receive from Field?

Components used in Field must handle the two following properties: input and meta. Please check out the description below.

input.onChange(value: *)

Allows to dispatch the new value of the field to the hocForm state. With this, all you have to do is to run input.onChange(theNewValue) to allow hocForm to use this new value at validation.

Example:

function TextInput({
  input = {},
}) {
  return (
    <input
      type="text"
      onChange={e => input.onChange(e.target.value)}
    />
  );
}

input.onBlur(value: *, values: Object) => Promise

Allows to run a validation on blur, the onBlur callback setted as property of the Field.

Example:

function TextInput({
  input = {},
}) {
  return (
    <input
      type="text"
      onBlur={e => input.onBlur && input.onBlur(e.target.value)}
    />
  );
}

Note: When Field runs the optional onBlur callback received from its props property, it runs this callback with two arguments:

  • value: *, which is the current value of the Field;
  • values: Object, object containing all fields keys with their respective value. As example, this argument can be useful if you need to compare a Β« confirmation password Β» field with a previous Β« create password Β» field.

This callback must a return a Promise:

  • Promise.resolve() if this blur validation succeeds;
  • Promise.reject(error) in case of failure.

Example:

<Field
  name="confirmPwd"
  component={Input}
  props={{
    label: 'Password confirmation *',
    type: 'password',
    onBlur: (currentValue, values) => (
      currentValue.trim() !== values.firstPassword)
        ? Promise.reject('Please enter the same password as below')
        : Promise.resolve()
    ),
  }}
/>

options.meta: Object

Object containing about a potential error on the field.

Example:

function TextInput({
  meta = {},
  input = {},
}) {
  return (
    <React.Fragment>
      <input
        type="text"
        onBlur={e => input.onBlur && input.onBlur(e.target.value)}
      />
      {meta.error && <span>{meta.error}</span>}
    </React.Fragment>
  );
}

Please check out a complete example here.

License

hocForm is MIT licensed.

hoc-form's People

Contributors

pacdiv avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

Forkers

ankit-github

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.