Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/blueberryapps/onion-form
React Redux form builder with great UX validations
https://github.com/blueberryapps/onion-form
blueberry-opensource form javascript react redux
Last synced: about 4 hours ago
JSON representation
React Redux form builder with great UX validations
- Host: GitHub
- URL: https://github.com/blueberryapps/onion-form
- Owner: blueberryapps
- Created: 2016-10-28T08:12:01.000Z (about 8 years ago)
- Default Branch: master
- Last Pushed: 2023-01-25T23:35:53.000Z (almost 2 years ago)
- Last Synced: 2024-10-28T17:51:48.382Z (10 days ago)
- Topics: blueberry-opensource, form, javascript, react, redux
- Language: JavaScript
- Homepage:
- Size: 835 KB
- Stars: 49
- Watchers: 29
- Forks: 2
- Open Issues: 18
-
Metadata Files:
- Readme: readme.md
Awesome Lists containing this project
README
![Onion Form](https://raw.githubusercontent.com/blueberryapps/onion-form/master/onion-form.png)
[![CircleCI](https://circleci.com/gh/blueberryapps/onion-form.svg?style=svg&circle-token=354f9bfd4c09ed529e4ff20019fc6668d03d9aa1)](https://circleci.com/gh/blueberryapps/onion-form) [![Dependency Status](https://dependencyci.com/github/blueberryapps/onion-form/badge)](https://dependencyci.com/github/blueberryapps/onion-form)> As a developer you are assigned with creating a registration form on Registration page
> with fields for first name, last name, e-mail and password, validate them and then
> send all these fields to API. Not again? This package will make your life easier by simplifying the dealing with forms.```
yarn add --save onion-form
```This package is only meant to be used together with Redux!
## TLDR
```javascript
import { Form, Field, Submit } from 'onion-form';{ console.log(errors) }}
onSubmit={({ values }) => { console.log(values) }}
validations={{ email: (value) => [((value && !value.match(/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i)) ? 'wrongFormat' : null)]}}
>
Sign In```
## Usage
```javascript
// Registration.react.js
import React, { Component } from 'react';
import { Form, Submit, connectField } from 'onion-form';// validations
const isRequired = (value) => ((!value) ? 'required' : null);
const emailNeedsToContainName = (_, otherValues) => ((!otherValues.email || otherValues.email.indexOf(otherValues.name) === -1) ? 'invalidEmail' : null);
const needLetters = (value) => (value && !value.match(/[a-zA-Z]+/i ? 'needLetters' : null);
const needNumbers = (value) => (value && !value.match(/\d+/i) ? 'needNumbers' : null);const validations = {
lastName: [isRequired],
email: [emailNeedsToContainName],
password: [needLetters, needNumbers]
};// You need to have a component which will receive all data by props
// error, hint, label, name, onBlur, onChange, onFocus, onionFormName, tooltip
const BasicInput = (props) => ();// Create your fields (can be used in different forms)
const FirstName = connectField('firstName')(BasicInput);
const LastName = connectField('lastName')(BasicInput);
const Email = connectField('email', { type: 'email' })(BasicInput);
const Password = connectField('password', { type: 'password' })(BasicInput);export default class RegistrationPage extends Component {
onSubmit({ values: { firstName, lastName, email, password } }) {
// apiCall('POST', { firstName, lastName, email, password })
}onError({ errors: { firstName, lastName, email, password } }) {
// alert, show flash message what ever you need to do when use tryies to
// submit form and gets validation errors
}render() {
return (
Registration
Register
)
}
}
```### Validations
There are three ways how you can add validations to your form:1. Pass an object with validations to the `Form` component as props (see examples above)
2. Pass an array of validations to the `connectField` function: `connectField('password', null, [isRequired(), password()])`
3. Specify the validations when the field component is being used:```js
export default class MyForm extends Component {
render() {
return (
Login
)
}
}
```All validations you specify will be used.
### Redux
!You need to add onion form reducer to your reducers and it must be under `onionForm` first level key!
```javascript
// store.js
import { createStore, combineReducers } from 'redux';
import { reducer as onionForm } from 'onion-form';const store = createStore(combineReducers({ onionForm }), {})
```## Action Creators
We have multiple action creators for communication with reducer:
`setMultipleFields`, `setFormFieldProperty`, `clearForm`, `clearFormProperty`, `setFieldValue`,
`setFieldLiveValidation`, `setFieldError`, `setFieldApiError`
All these actions accept `formName` as the first parameter which needs to match FORM_NAME in ``.> All connected fields get __formName__ from __context__.
But sometimes you need to communicate with fields from your code and repeating
name of the form can be exhausting, so we provide `createFormActions(formName)`
which returns all the actions with `formName` set.## connectField(FIELD_NAME, DEFAULT_PROPS)(DECORATED_COMPONENT)
__DEFAULT_PROPS__:
can be a plain __{}__ or a function which receives props as
the first parameter and needs to return __{}__. This function gets resolves in render on every rerender.
`(props) => ({ label: props.msg('key.to.label') })`__FIELD_VALUES_FROM_STATE__:
By default we store these values in redux state:
```javascript
{
value: '',
liveValidation: false,
error: null,
apiError: null
}
```
But you can use
`setMultipleFields(form, property, values)` or
`setFormFieldProperty(form, field, property, value)`
to set custom properties which will be then passed to the decorated component as well.__ONION_PROPS:__
`error`, `hint`, `label`, `name`, `onBlur`, `onChange`, `onFocus`, `onionFormName`, `tooltip`When you initialize a component in `render` you can pass the following PASSED_PROPS:
__PASSED_PROPS__
`label`, `onBlur`, `onFocus`, `onChange`, `tooltip`, `hint`, `defaultValue`
They will be transferred to the decorated component.
Functions passed by props (`onFocus`, `onChange`, `onBlur`) will get called too, after onion form callbacks.Passing order of props is: __DEFAULT_PROPS__ -> __FIELD_VALUES_FROM_STATE__ -> __ONION_PROPS__ -> __PASSED_PROPS__
You can pass `defaultValue` to component by (PROPS or __DEFAULT_PROPS__) to set that value to state on componentDid mount when field has no value already set.
## connectSubmit(DECORATED_COMPONENT)
You can use `connectSubmit` which will pass `onClick`, `valid`, `hasValues`, `hasErrors` and `disabled` as prop to the decorated component:
```js
// CustomSubmit.react.js
import { connectSubmit } from 'onion-form';const Button = ({ children, disabled, onClick }) => (
{children}
);export default const connectSubmit(Button);
```- `onClick`: callback function for submitting form
- `valid`: returns true/false based on fields validations runned against state (errors doesn't need to be in store)
- `hasErrors`: returns true if form is invalid (based on state from Redux)## Translations
You need to pass to component function `msg('keypath') => string`.
Implemetation is your thing but it needs to follow:
```
msg('key.foo') // returns translation for key.foo
msg(['foo', 'bar']) // returns translation for foo if exists else bar
```We use this function to resolve translations for the
`error`, `hint`, `label`, `tooltip`, `placeholder` props.__error__ is specific because we are trying to get text by:
```javascript
const error = field.error || field.apiError;
const errorText = error
? msg([`form.${formName}.errors.${error}`, `form.errors.${error}`, `errors.${error}`])
: '';
```others are easier, for example __label__:
```javascript
const labelText = label || defaultProps.label || msg([`form.${formName}.${fieldName}.label`, `form.${fieldName}.label`, `${fieldName}.label`]);
```# !For detailed documentation of all options do `yarn test`!
## Commands
* __yarn test__: runs mocha tests
* __yarn test:watch__: runs mocha test with watch option
* __yarn coverage__: create code coverage report## Made with love by
[![](https://camo.githubusercontent.com/d88ee6842f3ff2be96d11488aa0d878793aa67cd/68747470733a2f2f7777772e676f6f676c652e636f6d2f612f626c75656265727279617070732e636f6d2f696d616765732f6c6f676f2e676966)](https://www.blueberry.io)