# formwood

> A small library for building forms and validation with React.

Latest version **1.7.2** (published 2018-04-11) · MIT license · 0 weekly downloads

> **Deprecated.** This package is deprecated.

## Install

```sh
npm install formwood
pnpm add formwood
yarn add formwood
bun add formwood
```

## Health

**Score 10/100 (F)** — status: deprecated.

Negative: deprecated.

## Facts

| | |
|---|---|
| Version | 1.7.2 |
| Published | 2018-04-11 |
| First published | 2016-08-30 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 1 |
| Unpacked size | 26.8 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 6 |
| Author | Eric Valadas |
| Maintainers | ericvaladas |
| Keywords | react, forms, form, validation |

## Links

- npm: https://www.npmjs.com/package/formwood
- Repository: https://github.com/ericvaladas/formwood
- Issues: https://github.com/ericvaladas/formwood/issues
- npm.io page: https://npm.io/package/formwood

## Dependencies (1)

- [prop-types](https://npm.io/package/prop-types.md) ^15.6.0

## Alternatives

- [mobx-react](https://npm.io/package/mobx-react.md) — 2.8M weekly downloads
- [rc-tree](https://npm.io/package/rc-tree.md) — 2.6M weekly downloads
- [@react-oauth/google](https://npm.io/package/@react-oauth/google.md) — 1.3M weekly downloads
- [@wagmi/connectors](https://npm.io/package/@wagmi/connectors.md) — 877.0K weekly downloads
- [vee-validate](https://npm.io/package/vee-validate.md) — 836.4K weekly downloads

## Recent versions

- 1.7.2 (latest) — 2018-04-11
- 1.7.1 — 2018-02-24
- 1.7.0 — 2018-02-22
- 1.6.0 — 2018-02-05
- 1.5.5 — 2017-10-26
- 1.5.4 — 2017-10-11
- 1.5.3 — 2017-09-27
- 1.5.1 — 2017-04-28
- 1.4.2 — 2017-02-01
- 1.4.1 — 2016-11-03
- 1.4.0 — 2016-11-03
- 1.3.2 — 2016-10-05
- 1.3.1 — 2016-10-05
- 1.3.0 — 2016-10-05
- 1.1.4 — 2016-09-17
- … 25 more at https://npm.io/package/formwood/versions

## README

# Formwood

A small library for building forms and validation with React.

[![npm version](https://badge.fury.io/js/formwood.svg)](https://badge.fury.io/js/formwood)
[![Travis build status](http://img.shields.io/travis/ericvaladas/formwood.svg)](https://travis-ci.org/ericvaladas/formwood)
[![Coverage Status](https://coveralls.io/repos/github/ericvaladas/formwood/badge.svg?branch=master)](https://coveralls.io/github/ericvaladas/formwood?branch=master)
[![Dependency Status](https://david-dm.org/ericvaladas/formwood.svg)](https://david-dm.org/ericvaladas/formwood)
[![devDependency Status](https://david-dm.org/ericvaladas/formwood/dev-status.svg)](https://david-dm.org/ericvaladas/formwood?type=dev)

## Usage

Install the package with npm.
```sh
npm install --save formwood
```

Import the `Field` and `Form` modules.
```js
import {Field, Form} from 'formwood';
```

### Example
```js
const Input = Field(
  class extends React.Component {
    render() {
      return <input {...this.props.element}/>;
    }
  }
);

class MyForm extends React.Component {
  render() {
    return (
      <Form>
        <Input name="email" type="email"/>
        <Input name="password" type="password" validators={[minLength(6)]}/>
      </Form>
    );
  }
}
```

#### More Examples
https://ericvaladas.github.io/formwood-examples

### Field and Form
`Field` is a higher order component that will add the necessary functionality to your form fields. You must create a component for your input and then wrap the component with `Field`. Then, spread `this.props.element` on your input element. Lastly, use the `Form` component in place of a `form` tag when building your form.

Spreading `this.props.element` on the input element will add all your props, such as `name` and `type`, as well as an `onChange` and `defaultValue` prop. The `onChange` handler will store the value of the input in its state, which is later used for form values and validation. The `defaultValue` prop will set the input with an initial value provided by the `Form`.

**Note: `name` is a required prop as it is the lookup key for the field's value.**

### Form submission
When a form is submitted, all fields will have their validators run. The `onSubmit` event handler is passed an object containing the form's validity and its values.
```js
class MyForm extends React.Component {
  handleSubmit(form) {
    if (form.valid) {
      console.log('Form values:', form.values);
    }
  },

  render() {
    return (
      <Form onSubmit={this.handleSubmit}>
        <Input name="username" type="text"/>
      </Form>
    );
  }
}
```

### Initial Values
You can pass initial values to your fields by adding the `values` prop to the `Form`.
```js
class MyForm extends React.Component {
  render() {
    const values = {
      firstName: 'Eric',
      lastName: 'Valadas'
    };

    return (
      <Form values={values}>
        <Input name="firstName" type="text"/>
        <Input name="lastName" type="text"/>
      </Form>
    );
  }
}
```

### Validators
Validators are simply functions that return an error message.
```js
function minLength(length) {
  return value => {
    if (!value || value.length < length) {
      return `Must be at least ${length} characters`;
    }
  };
}

class MyForm extends React.Component {
  render() {
    return (
      <Form>
        <Input name="username" type="text" validators={[minLength(3)]}/>
      </Form>
    );
  }
}
```
The validation message will be passed to your field component via the `message` prop. If a validator does not return a message, it is considered valid.
```js
const Input = Field(
  class extends React.Component {
    render() {
      let className = "form-group";
      if (!this.props.valid) {
        className += " has-error";
      }
      return (
        <div className={className}>
          <label className="control-label" htmlFor={this.props.id}>{this.props.label}</label>
          <input className="form-control" {...this.props.element}/>
          <span className="help-block">{this.props.message}</span>
        </div>
      );
    }
  }
);
```

### Validation
All fields have a `validate` function that will run through their list of validators. By default, `validate` is only called when the form is submitted. However, this function is passed down as a prop and can be called whenever you like. Here's an example of validating a field as you type.
```js
const Input = Field(
  class extends React.Component {
    handleChange(e) {
      this.props.element.onChange(e).then(this.props.validate);
    },

    render() {
      return (
        <input {...this.props.element} onChange={e => this.handleChange(e)}/>
      );
    }
  }
);
```

You can also add field messages to your form which can be useful for things like server-side validation errors after submitting the form.
```js
class MyForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {messages: {}};
  }

  handleSubmit() {
    this.setState({
      messages: {username: 'Username already exists'}
    });
  },

  render() {
    return (
      <Form messages={this.state.messages} onSubmit={this.handleSubmit}>
        <Input name="username" type="text"/>
      </Form>
    );
  }
}
```

## Nested Components
The `Form` component uses a `form` prop to provide field registration functions, initial values, and messages to its child components. However, if you want to nest a `Field` component inside another component, you will need to pass the `form` prop manually.
```js
class MyComponent extends React.Component {
  render() {
    return <Input name="username" type="text" form={this.props.form}/>
  }
}

class MyForm extends React.Component {
  render() {
    <Form>
      <MyComponent/>
    </Form>
  }
}
```

## API
### Form
You can obtain a `Form` instance by adding a `ref` prop to your form.
```js
render() {
  return (
    <Form ref={(form) => { this.form = form; }}>
      ...
    </Form>
  );
}
```
| Property | Type | Returns | Description |
| --- | --- | --- | --- |
| `fields` | `object` | `object` | `{fieldName: [field, ...], ...}` |
| `getCheckboxValues(fieldName)` | `function` | `Array` | An array of field values |
| `getField(fieldName)` | `function` | `Field instance` | The most recently changed field for the given name |
| `handleSubmit(e)` | `function` | `Promise` | Calls `validate` then calls `props.onSubmit` |
| `invalidFields` | `object` | `object` | `{fieldName: field, ...}` |
| `validate()` | `function` | `Promise` | Calls `validate` on all fields |
| `values()` | `function` | `object` | `{fieldName: fieldValue, ...}` |

| Prop | Description |
| --- | --- |
| [`onSubmit`](#form-submission) | Passes an additional form object argument to your handler<br>`onSubmit(e, {valid: [bool], values: {...}}` |
| [`values`](#initial-values) | An object that contains values for the form's fields |
| [`messages`](#validation) | An object that contains messages for the form's fields |

### Field
These properties are passed down to your field via props.

| Property | Type | Returns | Description |
| --- | --- | --- | --- |
| `handleChange(e)` | `function` | `Promise` | Sets the `value` property of the state |
| `validate()` | `function` | `boolean` | Calls each validator and sets the `valid` and `message` properties of the state |

| Prop | Description |
| --- | --- |
| `element` | Contains essential props (listed below) and any prop you pass to your field |
| `element.defaultChecked` | The initial checked value for the element |
| `element.defaultValue` | The initial value for the element |
| [`element.onChange`](#validation) | The field's `handleChange` function |
| `message` | The message returned by a validator or a form's `messages` prop |
| `valid` | The valid property in the field's state. The initial value is `true` |
| `validate` | The field's `validate` function |
| `validators` | An array of validators |
| `value` | The value property in the field's state |

**Note: `name` is a required prop that you must pass to your field as it is the lookup key for the field's value.**

---
_Source: https://npm.io/package/formwood · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
