react-form-with-constraints-bs4beta
TypeScript icon, indicating that this package has built-in type declarations

0.1.0 • Public • Published

react-form-with-constraints

npm version Build Status codecov gzip size

Simple form validation for React in ~400 lines of code

Introduction: what is HTML5 form validation?

<form>
  <label for="email">Email:</label>
  <input type="email" id="email" required>
  <button>Submit</button>
</form>

input required input type="email"

The required HTML5 attribute specifies that the user must fill in a value, type="email" checks that the entered text looks like an email address.

Resources:

What react-form-with-constraints brings

  • Minimal API and footprint
  • Control HTML5 error messages: <FieldFeedback when="valueMissing">My custom error message</FieldFeedback>
  • Custom constraints: <FieldFeedback when={value => ...}>
  • Warnings and infos: <FieldFeedback ... warning>, <FieldFeedback ... info>
  • No dependency beside React (no Redux, MobX...)
  • No special component like <TextField>, just plain old <input> or whatever you like
  • Re-render only what's necessary
  • ...
<input type="password" name="password"
       value={this.state.password} onChange={this.handleChange}
       required pattern=".{5,}" />
<FieldFeedbacks for="password" show="all">
  <FieldFeedback when="valueMissing" />
  <FieldFeedback when="patternMismatch">
    Should be at least 5 characters long
  </FieldFeedback>
  <FieldFeedback when={value => !/\d/.test(value)} warning>
    Should contain numbers
  </FieldFeedback>
  <FieldFeedback when={value => !/[a-z]/.test(value)} warning>
    Should contain small letters
  </FieldFeedback>
  <FieldFeedback when={value => !/[A-Z]/.test(value)} warning>
    Should contain capital letters
  </FieldFeedback>
  <FieldFeedback when={value => !/\W/.test(value)} warning>
    Should contain special characters
  </FieldFeedback>
</FieldFeedbacks>

Examples

example-password

Other examples inside the examples directory.

How it works

The API works the same way as React Router v4:

<Router>
  <Route exact path="/" component={Home} />
  <Route path="/news" component={NewsFeed} />
</Router>

It is also inspired by AngularJS ngMessages.

If you had to implement validation yourself, you would end up with a global object that tracks errors for each field. react-form-with-constraints works similarly (although not using setState). It uses React context to share the FieldsStore object across FieldFeedbacks and FieldFeedback.

API

The API reads like this: "for field when constraint violation display feedback", example:

<FieldFeedbacks for="password">
  <FieldFeedback when="valueMissing" />
  <FieldFeedback when="patternMismatch">Should be at least 5 characters long</FieldFeedback>
</FieldFeedbacks>
for field "password"
  when constraint violation "valueMissing"    display "the HTML5 error message (*)"
  when constraint violation "patternMismatch" display "Should be at least 5 characters long"

(*) element.validationMessage

  • FieldFeedbacks

    • for: string => refer to a name attribute (e.g <input name="username">), should be unique to the current form
    • show?: 'first' | 'all' => display the first error/warning encountered (default) or all of them

    Note: you can place FieldFeedbacks anywhere and have as many as you want for the same field

  • FieldFeedback

    • when:ValidityStatestring | '*' | function => HTML5 constraint violation name or a callback
    • error?: boolean => treat the feedback as an error (default)
    • warning?: boolean => treat the feedback as a warning
    • info?: boolean => treat the feedback as an info
  • FormWithConstraints

    • validateFields(...inputsOrNames: Array<Input | string>): void => should be called when a field changes or the form is submitted, will re-render the proper FieldFeedbacks
    • isValid(): boolean

Browser support

You can use HTML5 attributes like type="email", required, pattern..., in this case a recent browser is needed,...

<label htmlFor="username">Username</label>
<input type="email" name="username" id="username"
       value={this.state.username} onChange={this.handleChange}
       required />
<FieldFeedbacks for="username">
  <FieldFeedback when="*" />
</FieldFeedbacks>

...or ignore them and rely on when functions:

<label htmlFor="username">Username</label>
<input name="username" id="username"
       value={this.state.username} onChange={this.handleChange} />
<FieldFeedbacks for="username">
  <FieldFeedback when={value => value.length === 0}>Please fill out this field.</FieldFeedback>
  <FieldFeedback when={value => !/\S+@\S+/.test(value)}>Invalid email address.</FieldFeedback>
</FieldFeedbacks>

In the last case you will have to manage translations yourself.

react-form-with-constraints, like React 16, depends on the collection types Map and Set. If you support older browsers (<IE11) you will need a global polyfill such as core-js or babel-polyfill.

Notes

Dependents (0)

Package Sidebar

Install

npm i react-form-with-constraints-bs4beta

Weekly Downloads

1

Version

0.1.0

License

MIT

Last publish

Collaborators

  • marten_cz