This libraray is an experimental approach to bind forms and its inputs and editors together using the new React Context API. It aims to be fully customizable and composable. It´s only a set of Higher-Order-Components.
Because of the decoupled nature, Middlewares makes it easy to build custom Validations, Security Guards and other data interceptors.
ATTENTION this is not an ui library, it is just a set of tools to bind forms and its inputs together.
ATTENTION I need help with this project, so let me know if you want to help
- Uses React Context API (requires 16.3)
- Minimalistic approach
- validation-as-middleware approach
- Does not tell you how to design
- Helps you with data flow only
- Decouple form, validation and inputs completely from each other
- Built as composable Higher-Order-Components
- Focus on pure & stateless components
- Support nesting
- Support unopinionated validation
- So you are building a lot of user inputs, e.g in enterprise admin dashboards. You are tired of connecting your forms and inputs together, drilling your callbacks deep down the rabbit whole. Then
react-formular
let´s you build your basic set of form and input elements that are tied together and you only need to take care of the design and structure. - You build a UI Library and want a easy way to just include the logic of binding forms to its inputs. With
react-formular
you have full control over your components, style and structuring.
# not published yet
npm install --save react-formular
There are basically two main functionalities.
- providing a context where data for the forms live in
- consuming the data, transform it and send it back up
- connecting both together
For this there are two basic Higher-Order-Components which can be created
provides the data context and returns a HOC in which you can pass initialData
and onChange
import React from 'react'
import { provideFormular } from 'react-formular'
const Form = provideFormular(({children, ...props}) => (
<form {...props}>
{children}
</form>
))
// how to use
render(
<Form initialData={data} onChange={newData => console.log(newData)} />
)
creates an connected HOC which can be bound to a specific property in the data object.
The WrappedComponent wil receive the value
and the field-bound update
function.
// Example of a connected Input
import React from 'react'
import { withFormField } from 'react-formular'
const SimpleField = withFormField(({ value, update, ...props}) => (
<input {...props} value={value} onChange={e => update(e.target.value)} />
))
// how to use
render(
<Form initialData={data} onChange={newData => console.log(newData)}>
<SimpleField field="myProperty" type="text" />
</Form>
)
creates a helper HOC that is a formular
data consumer.
It expects a function as first argument that will be called with and that function should
return a new Element.
{
// the data from a `formular` context
"data": {},
// the update function to call on change
"update": (field | newData = {}, value: undefined) => { /*...*/ },
// other props that will be passed when the HOC is created
...props
}
It helps you with building Components that need full access to the form data.
the HOC withFormField
uses it under the hood to connect it to one single field.
const FormAwareComponent = formAware(
({ data, update, ...props }) => (
// consume data, call update
)
)
A convenient function that uses formAware
. It in constrast supports non-functional components.
const ResetButton = withForm(({ update, ...props }) => (
return (<Button {...props} onClick={ update({}) }>Reset</Button>)
))
a Middleware Component is an easy way to step into the update process of the data flow. Data flows for example from an Input to the Form. So in case you want to check if the data that flows is correct, you can step in the middle and check the data. You can also think of it as an way to validate your data, but I named it Middleware, because I think there is more than validation.
the Middleware
component expects the use
prop which will be called as follows: (data, update, fail) => ...
data
is the changed data from descending componentsupdate(data)
is a function you should call with the data that need to be commitedfail(errors)
as a function you should call with an object, where very key is the field having an error
const update = (data) => console.log(data)
(
<Form onChange={update}>
<Middleware use={(data, update, fail) => (/*...*/)}>
<Input />
</Middleware>
</Form>
)
react-formular
does not tell you how or where to validate your data. But this library gives you a usefull helper. It´s the Middleware
Component and you can use it to build a Validator.
import { validate } from 'email-validator'
const EmailValidator = ({
field, children, errorMessage = 'Please use a correct email'
}) => (
<Middleware use={(data, update, fail) => {
if (validate(data[field])) {
update(data)
} else {
fail({[field]: errorMessage})
}
}}>
{ children }
</Middleware>
)
creates a HOC that passes you the error
or the errors
props.
If you build your Component with the field
prop, then your ErrorComponent will only
be called when the actual field is invalid and only the error
prop will be set.
If you do not specify the field
prop, then you will receive the errors
prop, which will be an object with all the field => errorMessage key-value pairs.
// An Label for a single field error
const ErrorLabel = withError(({error}) => (
<div className="has-error">
{ error }
</div>
))
render(
<Form initialData={data} onChange={onChange}>
<Validator onValidate={onValidate}>
<Input field="hello" type="text" />
+ <ErrorLabel field="hello" />
<Input field="world" type="text" />
+ <ErrorLabel field="world" />
</Validator>
</Form>
)
you can also build an input element so it recevices the error for the field.
const RawInput = ({ value, update, error, className = '', ...props }) => (
<input
{...props}
className={`${className} ${error ? 'has-error' : ''}`}
value={value}
data-error={error}
onChange={e => update(e.target.value)}
/>
)
const SimpleField = withError(withFormField(RawInput))
Currently the README does not contain every functionality
- explain
provideFormular
- explain
withFormField
- explain
formAware
- explain
withForm
- explain
withValidation
- explain
withError
- describe Nesting
- describe data-flow
- describe guards and validation
- Build Examples
- Actual implemenations for popular UI libraries
- Material UI
- API Reference
- Testing
MIT © theluk