All Projects → blueberryapps → onion-form

blueberryapps / onion-form

Licence: other
React Redux form builder with great UX validations

Programming Languages

javascript
184084 projects - #8 most used programming language
shell
77523 projects

Projects that are alternatives of or similar to onion-form

stook
A minimalist design state management library for React.
Stars: ✭ 86 (+72%)
Mutual labels:  form
Rails-4-ElasticSearch-dynamic-facets
Rails 4 ElasticSearch integration with dynamic facets
Stars: ✭ 16 (-68%)
Mutual labels:  form
translation-engine
A Rails engine for sending and receiving translations from Translation Server
Stars: ✭ 14 (-72%)
Mutual labels:  blueberry-opensource
react-html-form
Friendly form library for React ✌️
Stars: ✭ 58 (+16%)
Mutual labels:  form
BulkPDF
BulkPDF is a free and easy to use open source software, which allows to automatically fill an existing PDF form with differen values. Only a spreadsheet (Microsoft Excel 2007/2010/2013, LibreOffice or OpenOffice Calc) with the desired values is required.
Stars: ✭ 94 (+88%)
Mutual labels:  form
form-create-designer
好用的vue可视化表单设计器
Stars: ✭ 634 (+1168%)
Mutual labels:  form
TextFieldsTraversalController
A controller to manage the traversal of a collection of textfields.
Stars: ✭ 15 (-70%)
Mutual labels:  form
typo3-formlog
Form log for TYPO3
Stars: ✭ 16 (-68%)
Mutual labels:  form
laravel-nova-nested-form
This package allows you to include your nested relationships' forms into a parent form.
Stars: ✭ 225 (+350%)
Mutual labels:  form
vue3-form-validation
Vue Composition Function for Form Validation
Stars: ✭ 18 (-64%)
Mutual labels:  form
grapesjs-plugin-forms
Set of form components and blocks for the GrapesJS editor
Stars: ✭ 39 (-22%)
Mutual labels:  form
jquery.niceform
The jQuery plugin for validation and post form data to server
Stars: ✭ 16 (-68%)
Mutual labels:  form
EasyForm-Android
该项目是一个android端用于生成复杂表格的库。可以用来做像Excel表格那样的UI界面。
Stars: ✭ 17 (-66%)
Mutual labels:  form
bulma-material-form
Material Design Form Elements for Bulma (CSS Only)
Stars: ✭ 26 (-48%)
Mutual labels:  form
ngx-typed-forms
Extends Angular reactive forms strongly typed
Stars: ✭ 27 (-46%)
Mutual labels:  form
dynamic-input-fields-reactjs
Example of the dynamic input fields in ReactJS
Stars: ✭ 31 (-38%)
Mutual labels:  form
vue-auto-form
A vue2 component that helpers to easily create basic forms with automatic insert and update events, and automatic reactive validation.
Stars: ✭ 39 (-22%)
Mutual labels:  form
react-native-paper-form-builder
React Native Paper Form Builder with inbuilt Validation, dropdown, autocomplete, checkbox, switch and radio inputs.
Stars: ✭ 95 (+90%)
Mutual labels:  form
vue-use-form
✅ A Vue.js composition API function to validate forms
Stars: ✭ 97 (+94%)
Mutual labels:  form
SwiftUIFormValidator
Declarative form validator for SwiftUI.
Stars: ✭ 34 (-32%)
Mutual labels:  form

Onion Form CircleCI Dependency Status

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

import { Form, Field, Submit } from 'onion-form';

<Form
  name="signIn"
  onError={({ errors }) => { 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)]}}
>
  <Field name='email' type='email' />
  <Field name='password' type='password' />
  <Submit>Sign In</Submit>
</Form>

Usage

// 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) => (<input type="text" {...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 (
      <div>
        <h1>Registration</h1>
        <Form
          name="myRegistrationForm"
          onSubmit={this.onSubmit.bind(this)}
          onError={this.onError.bind(this)}
          validations={validations}
        >
          <FirstName label="Your first name" />
          <LastName />
          <Email />
          <Password />
          <Submit>Register</Submit>
        </Form>
      </div>
    )
  }
}

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:
export default class MyForm extends Component {
  render() {
    return (
      <Form name="myForm">
        <Email validations={[isRequired(), email()]} />
        <Password validations={[isRequired(), password()]}/>
        <Submit>Login</Submit>
      </Form>
    )
  }
}

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!

// 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 <Form name=FORM_NAME/>.

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:

{
  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:

// CustomSubmit.react.js
import { connectSubmit } from 'onion-form';

const Button = ({ children, disabled, onClick }) => (
  <button disabled={disabled} onClick={onClick} type="submit">{children}</button>
);

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:

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:

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

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].