Nuclear Planning Manual

    TypeScript icon, indicating that this package has built-in type declarations

    0.1.0 • Public • Published


    npm version Build Status codecov gzip size

    Simple form validation for React in ~400 lines of code

    Introduction: what is HTML5 form validation?

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

    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.


    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 when={value => !/\d/.test(value)} warning>
        Should contain numbers
      <FieldFeedback when={value => !/[a-z]/.test(value)} warning>
        Should contain small letters
      <FieldFeedback when={value => !/[A-Z]/.test(value)} warning>
        Should contain capital letters
      <FieldFeedback when={value => !/\W/.test(value)} warning>
        Should contain special characters



    Other examples inside the examples directory.

    How it works

    The API works the same way as React Router v4:

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

    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.


    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>
    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="*" />

    ...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>

    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.





    npm i react-form-with-constraints-bs4beta

    DownloadsWeekly Downloads






    Last publish


    • marten_cz