npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

formulary

v0.3.0

Published

React components for easy form implementation.

Downloads

10

Readme

☄️ 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.