https://github.com/cantonjs/react-form-mobx
🗄 Declarative Form components for React, built on top of MobX
https://github.com/cantonjs/react-form-mobx
array form form-data mobx nested-objects react react-component validation
Last synced: 10 months ago
JSON representation
🗄 Declarative Form components for React, built on top of MobX
- Host: GitHub
- URL: https://github.com/cantonjs/react-form-mobx
- Owner: cantonjs
- License: mit
- Created: 2018-05-29T15:54:39.000Z (almost 8 years ago)
- Default Branch: master
- Last Pushed: 2018-10-26T10:45:24.000Z (over 7 years ago)
- Last Synced: 2025-06-17T12:44:57.926Z (10 months ago)
- Topics: array, form, form-data, mobx, nested-objects, react, react-component, validation
- Language: JavaScript
- Homepage: https://codesandbox.io/s/52v7y2v304
- Size: 320 KB
- Stars: 6
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE.md
Awesome Lists containing this project
README
# react-form-mobx
[](https://circleci.com/gh/cantonjs/react-form-mobx)
[](https://travis-ci.org/cantonjs/react-form-mobx)
[](https://coveralls.io/github/cantonjs/react-form-mobx?branch=master)
[](http://makeapullrequest.com)
[](https://github.com/cantonjs/react-form-mobx/blob/master/LICENSE.md)
Declarative Form components for [React](https://reactjs.org/), built on top of [MobX](https://mobx.js.org/)

## Table of Contents
- [Table of Contents](#table-of-contents)
- [Philosophy](#philosophy)
- [Features Included](#features-included)
- [Features NOT Included](#features-not-included)
- [Live Demo](#live-demo)
- [Getting Started](#getting-started)
- [Installing](#installing)
- [Usage](#usage)
- [Advanced Guides](#advanced-guides)
- [Dynamic Array Items](#dynamic-array-items)
- [Creating Custom Input Component](#creating-custom-input-component)
- [References](#references)
- [Form Component](#form-component)
- [Input Components](#input-components)
- [ObjectOf Component](#objectof-component)
- [ArrayOf Component](#arrayof-component)
- [Submit, Reset, Clear Component](#submit-reset-clear-component)
- [Demon Component](#demon-component)
- [DemonButton Component](#demonbutton-component)
- [License](#license)
## Philosophy
Declarative, just like React and HTML
### Features Included
- Support nested objects and arrays
- Easy to create custom Input (or Select, Checkbox, Radio, etc) components
- Easy to push, update or remove array items
- Built-in validations (eg `required`, `pattern`, `enum`, etc)
- Built-in formats (eg `integer`, `number`, `boolean`, etc)
- Support data transformers / filters
### Features NOT Included
- No styles, just the original appearance, but you could add style easily
- No HTTP requests, but you could choose any HTTP request library you like
## Live Demo
[Live demo on codesandbox](https://codesandbox.io/s/52v7y2v304)
## Getting Started
### Installing
```bash
yarn add react-form-mobx
```
You may also need to install `react`, `mobx` and `mobx-react`
```bash
yarn add react mobx mobx-react react-form-mobx
```
### Usage
```jsx
import React, { Component } from 'react';
import { Form, Input, ObjectOf } from 'react-form-mobx';
export default class MyFriend extends Component {
myData = {
name: 'Luke Skywalker',
height: 172,
colors: {
hair: 'blond',
skin: 'fair',
},
},
handleSubmit = (data) => {
console.log('data', data);
};
render() {
return (
);
}
}
```
## Advanced Guides
### Dynamic Array Items
```jsx
import React, { Component } from 'react';
import { Form, Input, ArrayOf } from 'react-form-mobx';
export default class MyFriend extends Component {
myData = {
name: 'Luke Skywalker',
starships: ['X-wing', 'Imperial shuttle'],
},
handleSubmit = (data) => {
console.log('data', data);
};
render() {
return (
{(starships, { push, removeBy }) =>
{starships.map((starship) =>
Remove
)}
Add Starship
}
);
}
}
```
### Creating Custom Input Component
**MyInput.js**
```jsx
import React, { Component } from "react";
import { Demon } from "react-form-mobx";
export default class MyInput extends Component {
render() {
return (
{(props, { isInvalid, errorMessage }) => (
{isInvalid && {errorMessage}}
)}
);
}
}
```
**MyApp.js**
```jsx
import React, { Component } from "react";
import { Form } from "react-form-mobx";
import MyInput from "./MyInput";
export default class MyApp extends Component {
render() {
return (
{/* ... */}
);
}
}
```
## References
### Form Component
```jsx
import { Form } from 'react-form-mobx';
```
Form component, just like HTML `form` component.
#### Props
| Property | Description | Type | Default |
| ------------- | ------------------------------------------------------------------- | -------- | ------- |
| value | Form data | Object | `{}` |
| onSubmit | Defines a function will be called when form submit | Function | |
| onValid | Defines a function will be called when form is valid | Function | |
| onInvalid | Defines a function will be called when form is invalid | Function | |
| onValidChange | Defines a function will be called when form valid status changed | Function | |
| onChange | Defines a function will be called when form data changed | Function | |
| inputFilter | Defines a filter function will be called when providing a new value | Function | |
| outputFilter | Defines a filter function will be called when getting output value | Function | |
### Input Components
```jsx
import { Input, Checkbox, Radio, Select, TextArea } from 'react-form-mobx';
```
These Input Components mean `Input`, `Checkbox`, `Radio`, `Select`, `TextArea` or other custom input components created by `Demon`.
#### Props
| Property | Description | Type | Default |
| ---------------- | ---------------------------------------------------------------------------- | -------------------------------------------------------------------- | ------- |
| name | Field name | String `Required` | |
| defaultValue | Default value when value is empty | Any | |
| defaultChecked | Default checked, only work in checkable components (eg: `Checkbox`, `Radio`) | Boolean | |
| format | Data format | "integer", "number", "string", "boolean", "date", "time", "dateTime" | |
| required | Indicates whether field is required | Boolean | `false` |
| enum | Validate a value from a list of possible values | Array of `String` | `[]` |
| pattern | Validate from a regular expression | RegExp | |
| maxLength | Validate a max length of the field | Number | |
| minLength | Validate a min length of the field | Number | |
| maximum | Validate if the field is less than or exactly equal to "maximum" | Number | |
| exclusiveMaximum | Validate if the field is less than (not equal to) "exclusiveMaximum" | Number | |
| minimum | Validate if the field is greater than or exactly equal to "minimum" | Number | |
| exclusiveMinimum | Validate if the field is greater than or exactly equal to "exclusiveMinimum" | Number | |
| validation | Defines a validator function, should throw error if invalid | Function | |
| inputFilter | Defines a filter function will be called when providing a new value to form | Function | |
| outputFilter | Defines a filter function will be called when getting output value from form | Function | |
| withEmpty | Indicates whether submit empty value or not | "auto", `true`, `false` | "auto" |
The rest of the props are exactly the same as the original [DOM attributes](https://reactjs.org/docs/dom-elements.html#all-supported-html-attributes).
##### Notes
- `withEmpty`: If value is empty (saying `""`, `undefined`, `null`, `{}` or `[]`):
* `"auto"` (Default): Will submit empty value only if pristine value is NOT empty
* `true`: Will submit empty value
* `false`: Will not submit empty value
### ObjectOf Component
```jsx
import { ObjectOf } from 'react-form-mobx';
```
`ObjectOf` component provides nested fields.
#### Props
| Property | Description | Type | Default |
| ------------ | ---------------------------------------------------------------------------- | ----------------- | ------- |
| name | Field name | String `Required` | |
| children | Nested input nodes | Node `Required` | |
| onChange | Defines a function will be called when data changed | Function | |
| inputFilter | Defines a filter function will be called when providing a new value to form | Function | |
| outputFilter | Defines a filter function will be called when getting output value from form | Function | |
### ArrayOf Component
```jsx
import { ArrayOf } from 'react-form-mobx';
```
`ArrayOf` component provides array fields, and could be push, update or remove easily.
#### Props
| Property | Description | Type | Default |
| ------------ | ---------------------------------------------------------------------------- | --------------------------- | ------- |
| name | Field name | String `Required` | |
| children | Nested input nodes or function child that should return a node | Node or Function `Required` | |
| onChange | Defines a function will be called when data changed | Function | |
| inputFilter | Defines a filter function will be called when providing a new value to form | Function | |
| outputFilter | Defines a filter function will be called when getting output value from form | Function | |
#### Function Child
If `children` prop is a callback renderer function, it will provide two arguments:
- `names` \: An array of unique names that could be used as the `key` and `name` props of chidren components
- `helper` \: A helper object to manipulate the array:
* `push()` \: To push a new item
* `remove(name)` \: To remove a item by `name`
* `removeBy(name)` \: To create and return a `remove(name)` currying function
Please checkout [Dynamic Array Items](#dynamic-array-items) for usage example.
### Submit, Reset, Clear Component
```jsx
import { Submit, Reset, Clear } from 'react-form-mobx';
```
- `Submit`: Just like HTML `button` component. Will emit `onSubmit()` in `Form` when click.
- `Reset`: Just like HTML `button` component. Will reset all input values to pristine values in `Form` when click
- `Clear`: Just like HTML `button` component. Will clear all input values in `Form` when click.
#### Props
| Property | Description | Type | Default |
| -------- | ----------- | ---- | ------- |
| children | children | Node | |
The rest of the props are exactly the same as the original [DOM attributes](https://reactjs.org/docs/dom-elements.html#all-supported-html-attributes).
### Demon Component
```jsx
import { Demon } from 'react-form-mobx';
```
`Demon` component is the core of creating custom input components.
#### Props
| Property | Description | Type | Default |
| ------------------------- | ------------------------------------------------------------ | ------------------- | ---------------------------------- |
| name | Field name | String `Required` | |
| children | Function child that should return a node | Function `Required` | |
| forwardedProps | Forward props, `Demon` will decide to handle or forward them | Object | `{}` |
| checkable | Indicates whether the component is checkable | Boolean | `false` |
| getValueFromChangeEvent | Defines a function to get `value` in `onChange` arguments | Function | `(ev) => ev.currentTarget.value` |
| getCheckedFromChangeEvent | Defines a function to get `checked` in `onChange` arguments | Function | `(ev) => ev.currentTarget.checked` |
| getKeyFromKeyPressEvent | Defines a function to get `key` in `onPress` arguments | Function | `(ev) => ev.key` |
| propOnChange | Defines the prop name of change event | String | "onChange" |
| propOnKeyPress | Defines the prop name of key press event | String | "onKeyPress" |
| propOnBlur | Defines the prop name of blur event | String | "onBlur" |
#### Function Child
`children` prop provides two arguments:
- `proxyProps` \: Forwarded props object including `value` or `checked`, but excluding `name`, `format`, `enum` and other props only work in `Demon` component. Can be directly pass to child component (like ``)
- `validState` \: Valid state helper object, including:
* `errorMessage` \: Error message. Would be empty if the status is valid
* `isValid` \: Would be true if the status is valid
* `isInvalid` \: Would be true if the status is invalid
* `isTouched` \: Is touched or not. Useful if you don't want to show `errorMessage` when field is not touched
#### Proxied Props
By default, `onChange`, `onKeyPress`, `onBlur` props will be proxied.
- `onChange`: `Demon` need to get the changed `value` or `checked` from the `change` event object to update value. You can change the getting function by setting `getValueFromChangeEvent` or `getCheckedFromChangeEvent` prop to `Demon` component.
- `onKeyPress`: `Demon` need to get the `key` from the `keyPress` event object to decide to submit. You can change the getting function by settting `propOnKeyPress` prop to `Demon` component
- `onBlur`: `Demon` need to listen to the `blur` event to set `isTouched` to `true`
Please checkout [Creating Custom Input Component](#creating-custom-input-component) for usage example.
### DemonButton Component
```jsx
import { DemonButton } from 'react-form-mobx';
```
`DemonButton` component is the core of creating custom button (Submit, Reset or Clear) components.
#### Props
| Property | Description | Type | Default |
| ----------------------- | ------------------------------------------------------------------ | -------------------------- | ---------------- |
| children | Function child that should return a node | Function `Required` | |
| type | Button type | "submit", "reset", "clear" | "submit" |
| forwardedProps | Forward props, `DemonButton` will decide to handle or forward them | Object | `{}` |
| getKeyFromKeyPressEvent | Defines a function to get `key` in `onPress` arguments | Function | `(ev) => ev.key` |
| propOnKeyPress | Defines the prop name of key press event | String | "onKeyPress" |
#### Function Child
`children` prop provides one argument:
- `proxyProps` \: Forwarded props object. Can be directly pass to child component (like ``)
## License
MIT