react-form-with-constraints
Simple form validation for React in ~400 lines of code
Introduction: what is HTML5 form validation?
<form>
<label>Email:</label>
<input type="email" required>
<button>Submit</button>
</form>
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
- Control HTML5 error messages:
<FieldFeedback when="valueMissing">My custom error message</FieldFeedback>
- Custom constraints beyond HTML5:
<FieldFeedback when={value => ...}>
- Warnings:
<FieldFeedback ... warning>
- Infos:
<FieldFeedback ... info>
- Multiple feedbacks:
<FieldFeedbacks ... show="all">
<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>
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.
react-form-with-constraints demo
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"
-
FieldFeedbacks
for: string
=> refer to a name
attribute, e.g <input name="password">
show?: 'first' | 'all'
=> display the first error/warning encountered (default) or all of themchildren: FieldFeedback[]
-
FieldFeedback
when:
ValidityState
string | '*' | function
=> HTML5 constraint violation name or a callbackerror?: boolean
=> treat the feedback as an error (default)warning?: boolean
=> treat the feedback as a warninginfo?: boolean
=> treat the feedback as an infochildren?: string
=> the text to display or the HTML5 error message if undefined
-
FormWithConstraints
validateFields(...inputsOrNames: Array<Input | string>): void
=> should be called when an input
changes or the form
is submittedisValid(): boolean
Browser support
You can use HTML5 attributes like type="email"
, required
, pattern
..., in this case a recent browser is needed,...
<form onSubmit={this.handleSubmit} noValidate>
<label>Username</label>
<input type="email" name="username"
value={this.state.username} onChange={this.handleChange}
required />
<FieldFeedbacks for="username">
<FieldFeedback when="*" />
</FieldFeedbacks>
<button>Submit</button>
</form>
...or ignore them and rely on when
functions:
<form onSubmit={this.handleSubmit} noValidate>
<label>Username</label>
<input name="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>
<button>Submit</button>
</form>
In the last case you will have to manage translations yourself.
Notes
A readonly
or disabled
input won't trigger any HTML5 form constraint like required
.