formulary

0.3.0 • Public • Published

☄️ Formulary - React Forms ☄️· GitHub license npm version CircleCI

React Forms package offers easy to use forms with validations. It uses the new React Context API that was introduced in React 16.3.0. React Forms handles the form state for you and offer simply API to read/write to the state.

Useful link

Changelog: List of changes

Roadmap (future plans): List of features

Motivation

There already is a great library for managing forms, called react-redux. It uses Redux to keep the state. The advantage of using Redux is when:

  • you need to interact with your form data globally from your application
  • you use Redux time travel features to record user interaction

You can read more when you should use Redux in article You Might Not Need Redux from Dan Abramov.

But in the most cases you don´t need those capabilities or you use other state management library. So why should you buy into Redux just to create forms? You shouldn´t and that is the reason this library exists.

Instalation

npm install --save formulary

Peer dependencies

Make sure you have installed React and React DOM in the version 16.3 or higher.

npm install --save react react-dom

Examples

This example shows a simple form.

First we need to define how are the inputs displayed (i.e. twitter bootstrap, material-ui/react-toolbox or your custom components) Let´s define a simple input that only displays a given value and that handles value change (without validation or error messages)

const MyInput = props => (
  <input
    type={props.type}
    value={props.field.value}
    onChange={e => props.onChange(e.target.value)}
    onBlur={props.onBlur}
  />
);

Here we define the actual form component, the only thing we need to pass in is a way of handling the submitting. In our case onSubmit is a simple action that performs an remote API call to our backend.

Note that our Field components can be nested several levels deep and still have access to the form state thanks to the React Context API.

import { Form, Field } from 'formulary';
 
const MyForm = props => {
  onSubmit = (values, state) => {
    // Call backend with your favourite request library
    return axios.post('/api/login', values).then(
      res => {
        // ...handle result
      },
      err => {
        // ...handle errors, i.e.
        // you can set form field errors by rejecting the promise
        // and returning structure { fields: { <field-key>: [ ... ] }}
        return Promise.reject({
          fields: {
            username: ['Login credentials are not valid'],
          },
        });
      }
    );
  };
 
  return (
    <Form onSubmit={onSubmit}>
      <Field name="username" label="Jméno" value="JohnDoe">
        <MyInput type="text" />
      </Field>
 
      <Field name="password" label="Jméno" value="SecretPassword123">
        <MyInput type="password" />
      </Field>
 
      <input type="submit" value={'Submit'} />
    </Form>
  );
};

API

Field

Each Field component is passed these props.

Field handlers:

Key Description Signature
onChange Handles input changes, accepts the new input value onChange(value)
onFocus Focus event handler onFocus(event)
onBlur Blurring event handler, upon blurring the field is marked as touched onBlur(event)
onReset Resets the field to its initial value onReset()

Field values:

Key Type Description
value * Current field value
initialValue * Initial value
meta Object
meta.key string Field name
meta.label string Field label (is passed to the validation functions)
meta.pristine boolean User has NOT interacted with the field yet
meta.dirty boolean User has interacted with the field
meta.touched boolean Field has lost focus
meta.untouched boolean Field has NOT yet lost focus
meta.valid boolean All validation rules passes
meta.invalid boolean Some of the validation rules are not met
meta.validating boolean Validation in progress
functions Object
functions.parse function Parsing function (i.e. (value) => moment(value))
functions.transform function Transformating function (i.e. (value) => value.toUpperCase())
functions.format function Formatting function (i.e. (value) => moment.format('YYYY-MM-DD'))
functions.validate Array<function> Array of validation functions
errors Array<string> Array of error messages from validation rules

Value lifecycle

onChange(value) -> parse(value) -> transform(value) -> { state } -> format(value)

Form

Key Description Signature
onSubmit Will be fired only when the form is valid. Returning a rejected promise can be used to set errors on fields. onSubmit(values, state)

Validation

Using the default validation functions

Notice we are using different syntax for inputs, instead of passing children we are giving the component as a prop (component) and we pass other props from the Field component (type="text"). Both ways are equvivalent.

import { isEmail, isRequired } from '@alesmenzel/react-forms';
 
// Pass in a message
const email = isEmail('Invalid email address');
// Pass in a function that returns a message
const required = isRequired(field => `Field ${field.meta.label} is required`);
 
const MyForm = ({ onSubmit }) => {
  return (
    <Form onSubmit={onSubmit}>
      <Field
        name="email"
        label="Email"
        validate={email}
        component={MyInput}
        type="text"
      />
 
      <Field
        name="another_email"
        label="Required email"
        validate={[required, email]}
        component={MyInput}
        type="text"
      />
 
      <input type="submit" value={'Submit'} />
    </Form>
  );
};

As you can see the validate prop accepts both functions and an array of functions. In case of array, all rules must be met.

Built in validators

Numbers:

Name Description Signutare
minimum Check whether the value is at least min minimum(msg, min)
maximum Check whether the value is at most max maximum(msg, max)
range Check whether the value is at least min and at most max range(msg, min, max)
isNumber Check whether the value is a finite number isNumber(msg)
isInteger Check wheteher the value is an integer (a whole number) isInteger(msg)
isFloat Checks whether the value is a float isFloat(msg)

String:

Name Description Signutare
minimumLength Checks if value has at least min length minimumLength(msg, min)
maximumLength Checks if value has at most max length maximumLength(msg, max)
length Checks if value is at least min and at most max length length = (msg, min, max)
isEqual Checks whether the value is equal to comparison isEqual(msg, comparison)
isNotEqual Checks whether the value is not equal to comparison isNotEqual(msg, comparison)
isIn Checks whether the value equals to one of comparisons isIn(msg, comparisons)
isNotIn Checks whether the value does not equal to any of comparisons isNotIn(msg, comparisons)
pattern Checks whether the value matches pattern, flags are optional (and can be passed with the pattern directly /[A-Z]+/gi) pattern(msg, pattern, flags)

Required:

Name Description Signutare
isRequire.d Checks whether a value is set, note that zero is considered a valid value isRequired(msg)

Email:

Name Description Signutare
isEmail Checks for a valid email address (uses isemail module) isEmail(msg)

Using custom validation functions

You can also create a custom validator function. Here is a sample:

Validation functions should return error message if the rule is not met othervise return undefined.

import { getFunction, getMessage } from 'formulary'
 
export const isNumberEight = msg => {
  // enable passing a message or a function that returns a message
  const getMessage = getFunction(msg);
 
  return (field) => {
    const { value } = field;
 
    if (value !== 8) {
      return getMessage(field, { metadata: 'you can pass some metadata down' });
    }
 
    return undefined;
}

Contributing

The main goal of this repository is to make working with react forms easy without forcing to use other technologies, like Redux.

Code of Conduct

We adopted a Code of Conduct that we expect project participants to adhere to. Please read the full text so that you can understand what actions will and will not be tolerated.

License

This project is licensed under the terms of the MIT license.

Readme

Keywords

Package Sidebar

Install

npm i formulary

Weekly Downloads

1

Version

0.3.0

License

MIT

Unpacked Size

1.09 MB

Total Files

48

Last publish

Collaborators

  • alesmenzel