https://github.com/dsheiko/react-html5-form
Form validation component to connect React.js to HTML5 Constraint Validation API :boom:
https://github.com/dsheiko/react-html5-form
form html5 react reactjs redux validated validation
Last synced: 11 months ago
JSON representation
Form validation component to connect React.js to HTML5 Constraint Validation API :boom:
- Host: GitHub
- URL: https://github.com/dsheiko/react-html5-form
- Owner: dsheiko
- Created: 2018-05-03T12:39:43.000Z (almost 8 years ago)
- Default Branch: master
- Last Pushed: 2019-06-24T12:29:00.000Z (over 6 years ago)
- Last Synced: 2025-04-07T20:02:07.402Z (12 months ago)
- Topics: form, html5, react, reactjs, redux, validated, validation
- Language: JavaScript
- Homepage:
- Size: 1.56 MB
- Stars: 13
- Watchers: 2
- Forks: 8
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# React-html5-form
[](https://www.npmjs.com/package/react-html5-form)
[](https://www.npmjs.com/package/react-html5-form)
[](https://codecov.io/gh/dsheiko/react-html5-form)
[](https://github.com/facebook/jest)
[](https://travis-ci.org/dsheiko/react-html5-form)
With the package you don't need to re-create form validation logic every time. Instead you take full advantage of [HTML5 Constraint Validation API](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation). Besides the package expose no custom input components, instead it provides wrapper `InputGroup`, which binds inputs (according to configuration) in the children DOM nodes. Thus you can go with both HTML controls and 3rd-party input components.

## Highlights
- Input implementation agnostic, can be used any arbitrary input controls (HTML or 3rd-party React components)
- Standard HTML5 syntax for validation constraints (like ``)
- Can be extended with custom validators (again by using standard HTML5 API)
- Can be setup for custom validation messages per `input`/`ValidityState.Property`
- Form and input groups expose validity states, so you can use it to toggle scope error messages.
- Form and input groups expose reference to own instances for children DOM nodes. So you can, for example, subscribe for `input` event and run input group validation (e.g. see [On-the-fly validation](#on-the-fly-validation))
- Can maintain form state both ways: with React Context and [Redux](#connecting-to-redux-store)
## Overview
With `Form` we define scope of the form. The component exposes parameters `valid`, `error` and `form`. The first reflects actual validity state according to states of registered inputs. The second contains error message (can be set using API). The last one is instance of the component and provides access to the API.
With `InputGroup` we define a fieldset that contains one or more semantically related inputs (e.g. selects `day`, `month`, `year` usually go togather). The group expose `valid`, `error`, `errors` and `inputGroup` variables on children Nodes. So we can automatically toggle group error message and content `classList` depending on them.
We register inputs within `InputGroup` with `validate` prop. There we can specify a validator function, which will extend HTMP5 form validation logic. Very easily we can provide mapping for standard validation message (`translate` prop).

## Installation
```bash
npm i react-html5-form
```
## Demo
You can see the component in action at [LIVE DEMO](https://dsheiko.github.io/react-html5-form/) :tv:
- [source code](./demo/bootstrap/src/index.jsx) of example with HTML elements for inputs (styled with Bootstrap 4)
- [source code](./demo/materialui/src/index.jsx) of example with read-made components for inputs (styled with MaterialUI.Next)
- [source code](./demo/bootstrap-redux/src/index.jsx) of example with connection to Redux
## Form
Represents form
```js
import { Form } from "react-html5-form";
```
### Props
- `` `onSubmit` - (OPTIONAL) form submit handler
- `` `onMount` - (OPTIONAL) callback that gets invoked in `componentDidMount()`, it receives component instance as parameter
- `` `onUpdate` - (OPTIONAL) callback that gets invoked when form ready (all input groups registered) and when it changes validity state. It's intended to be used with Redux to update tree state
- any attributes of Form HTML element
### API
- `scrollIntoViewFirstInvalidInputGroup()` - scroll first input group in invalid state into view (happens automatically onSubmit)
- `checkValidityAndUpdateInputGroups()` - check form validity and update every input group
- `checkValidityAndUpdate()` - check form validity and update only form state (without updating input groups)
- `setError( message = "")` - set form scope error message
- `submit()` - submit form
- `getRef()` - get `Ref` instance pointed to the generated `FORM` element. Thus if you need to access the DOM node, you go with `form.getRef().current`
- `debugInputGroups( inx = null )` - get debug info about all registered inputs, or one matching given index
### Scope parameters
- `` `error` - error message set with `setError()`
- `` `valid` - form validity state
- `` `pristine` - true if user has not interacted with the form yet.
- `` `submitting` - true while form is being processed on submission
- `` `submitted` - true after form submitted
- `` `form` - link to the component API
> State properties `valid`, `pristine`, `submitting`, `submitted` are also available as element data-attributes e.g. `data-submitting="false"`
#### Defining component
```jsx
import React from "react";
import { render } from "react-dom";
import { Form } from "react-html5-form";
const MyForm = props => (
{({ error, valid }) => (
<>
Form content
>
)}
);
render( , document.getElementById( "app" ) );
```
`` creates `` wrapper for passed in children. It delegates properties to the produced HTML Element.
For example specified `id` ends up in the generated form.
#### Accessing `Form` API
```jsx
async function onSubmit( form ) {
form.setError("Opps, a server error");
return Promise.resolve();
};
const MyForm = props => (
{({ error, valid, pristine, submitting, form }) => (
<>
{ error && (
Oh snap! {error}
)
}
Form content
Submit
>
)}
);
```
The API can be accessed by `form` reference. Besides, any handler passed through `onSubmit` prop gets wrapped.
The component calls `setState` for `checkValidity` prior calling the specified handler. From the handler you can
access the API by reference like `form.setError`. What is more, we disable submit button until the user first interaction with the form and on form submission (`onSubmit is an asynchronous function / Promise; as it resolves the state property `submitting` set in false).
## InputGroup
`InputGroup` defines scope and API for a group of arbitrary inputs registered with `validate` prop. `InputGroup` exposes in the scope parameters that can be used to toggle group validation message(s), group state representation and to access the component API
```js
import { Form, InputGroup } from "react-html5-form";
```
### Props
- `validate` - (REQUIRED) register inputs to the group. Accepts either array of input names (to match `[name=*]`) or plain object out of pairs `name: custom validator`
```jsx
// Group of a single input
// Group of multiple inputs
// Custom validator
{
if ( !input.current.value.startsWith( "DE" ) ) {
input.setCustomValidity( "Code must start with DE" );
return false;
}
return true;
}
}}>
```
- `translate` - (OPTIONAL) set custom messages for validation constraints (see [ValidityState Properties](https://developer.mozilla.org/en-US/docs/Web/API/ValidityState))
```jsx
```
- `tag` - (OPTIONAL) define tag for the generated container HTML element (by default `div`)
```jsx
```
- `` `onMount` - (OPTIONAL) callback that gets invoked in `componentDidMount()`, it receives component instance as parameter
- `` `onUpdate` - (OPTIONAL) callback that gets invoked when form ready (all input groups registered) and when it changes validity state. It's intended to be used with Redux to update tree state
- any attributes of HTML element
### API
- `checkValidityAndUpdate()` - run `checkValidity()` and update the input group according to the actual validity state
- `getInputByName( name )` - access input fo the group by given input name
- `getValidationMessages()` - get list of all validation messages within the group
- `checkValidity()` - find out if the input group has not inputs in invalid state
- `getRef()` - get `Ref` instance pointed to the generated element. Thus if you need to access the DOM node, you go with `inputGroup.getRef().current`
### Scope parameters
- `` `error` - validation message for the first invalid input
- `` `errors` - array of validation messages for all the inputs
- `` `valid` - input group validity state (product of input states)
- `` `pristine` - true if user has not interacted with the form yet.
- `` `inputGroup` - link to the component API
#### Basic use
```jsx
{({ error, valid }) => (
Email address
{ error && (
{error}) }
)}
```
Here we define an input group with registered input matching `[name=email]`. We also specify a custom message for `ValidityState.valueMissing` constraint.
It means that during the validation the input has no value while having constraint attribute `required` the input group receive validation message `"C'mon! We need some value"` in scope parameter `error`.
#### Custom validators
```jsx
{
if ( !input.current.value.startsWith( "DE" ) ) {
input.setCustomValidity( "Code must start with DE." );
return false;
}
return true;
}
}}>
{({ error, valid }) => (
VAT Number (optional)
{ error && (
{error}) }
)}
```
Here we define a custom validator for `vatId` input (via `validate` prop). The validator checks if the current input value starts with `"DE"`.
If it dosn't we apply `setCustomValidity` method to set the input (and the group) in invalid state (the same as of HTML5 Constraint validation API).
#### Group with multiple inputs
```js
const validateDateTime = ( input ) => {
if ( input.current.value === "Choose..." ) {
input.setCustomValidity( `Please select ${input.current.title}` );
return false;
}
return true;
};
```
```jsx
{({ errors, valid }) => (
Day
Choose...
...
Month
Choose...
...
{ errors.map( ( error, key ) => (
{error} )) }
)}
```
On validation we receives `errors` array that contains validation messages for all the inputs registered in the group. So we can display the messages within the group container.
#### On-the-fly validation
Let's first define the `onInput` event handler:
```js
const onInput = ( e, inputGroup ) => {
inputGroup.checkValidityAndUpdate();
};
```
We use `checkValidityAndUpdate` method to actualize validity state and update the component.
Now we subscribe the component:
```jsx
{({ error, valid, inputGroup }) => (
First Name
onInput( e, inputGroup, form ) }
placeholder="Enter first name"/>
{ error && (
{error}) }
)}
```
Here while assigning event handler inline we delegate the instance of component to earlier created `onInput` function like `onInput={( e ) => onInput( e, inputGroup ) }`. Thus we can operate it when responding to the event.
## Input
Represents input element within input group scope.
### API
- `current` - input HTML element
- `setCustomValidity( message = "" )` - set the input in invalid state
- `checkValidity()` - returns boolean truthy when all the input in valid state
- `getValidationMessage()` - get validation message considering assigned custom message if any
## Connecting to Redux store
The package exposes reducer `html5form`, so one can connect form/input group/input states to the store:
```jsx
import React from "react";
import { render } from "react-dom";
import { createStore, combineReducers } from "redux";
import { Provider } from "react-redux";
import { App } from "./Containers/App.jsx";
import { html5form } from "react-html5-form";
const appReducer = combineReducers({
html5form
});
// Store creation
const store = createStore( appReducer );
render(
, document.getElementById( "app" ) );
```
Thus we get package-specific state tree in the store:

- See full example [here](./demo/bootstrap-redux/src/index.jsx)