All Projects → tkrotoff → React Form With Constraints

tkrotoff / React Form With Constraints

Licence: mit
Simple form validation for React

Programming Languages

typescript
32286 projects

Projects that are alternatives of or similar to React Form With Constraints

Usetheform
React library for composing declarative forms, manage their state, handling their validation and much more.
Stars: ✭ 40 (-65.81%)
Mutual labels:  validation, form-validation, form
Bootstrap Validate
A simple Form Validation Library for Bootstrap 3 and Bootstrap 4 not depending on jQuery.
Stars: ✭ 112 (-4.27%)
Mutual labels:  validation, form-validation, form
svelte-form
JSON Schema form for Svelte v3
Stars: ✭ 47 (-59.83%)
Mutual labels:  validation, form, form-validation
Pristine
Vanilla javascript form validation micro-library
Stars: ✭ 197 (+68.38%)
Mutual labels:  validation, form, html5
Hyperform
Capture form validation back from the browser
Stars: ✭ 729 (+523.08%)
Mutual labels:  validation, form-validation, html5
Resolvers
📋 Validation resolvers: Zod, Yup, Joi, Superstruct, and Vest.
Stars: ✭ 222 (+89.74%)
Mutual labels:  validation, form-validation, form
Just Validate
Lightweight (~4,5kb gzip) form validation in Javascript Vanilla, without dependencies, with customizable rules (including remote validation), customizable messages and customizable submit form with ajax helper.
Stars: ✭ 74 (-36.75%)
Mutual labels:  validation, form-validation, form
Form Validation.js
The most customizable validation framework for JavaScript.
Stars: ✭ 127 (+8.55%)
Mutual labels:  validation, form-validation, form
Formsy React
A form input builder and validator for React JS
Stars: ✭ 708 (+505.13%)
Mutual labels:  validation, form-validation, form
Bunny
BunnyJS - Lightweight native (vanilla) JavaScript (JS) and ECMAScript 6 (ES6) browser library, package of small stand-alone components without dependencies: FormData, upload, image preview, HTML5 validation, Autocomplete, Dropdown, Calendar, Datepicker, Ajax, Datatable, Pagination, URL, Template engine, Element positioning, smooth scrolling, routing, inversion of control and more. Simple syntax and architecture. Next generation jQuery and front-end framework. Documentation and examples available.
Stars: ✭ 473 (+304.27%)
Mutual labels:  validation, form-validation, form
Redux Form
A Higher Order Component using react-redux to keep form state in a Redux store
Stars: ✭ 12,597 (+10666.67%)
Mutual labels:  validation, form-validation, form
Ok
✔️ A tiny TypeScript library for form validation
Stars: ✭ 34 (-70.94%)
Mutual labels:  validation, form-validation, form
Neoform
✅ React form state management and validation
Stars: ✭ 162 (+38.46%)
Mutual labels:  validation, form-validation, form
formalizer
React hooks based form validation made for humans.
Stars: ✭ 12 (-89.74%)
Mutual labels:  validation, form, form-validation
Formhelper
ASP.NET Core - Transform server-side validations to client-side without writing any javascript code. (Compatible with Fluent Validation)
Stars: ✭ 155 (+32.48%)
Mutual labels:  validation, form-validation, form
Approvejs
A simple JavaScript validation library that doesn't interfere
Stars: ✭ 336 (+187.18%)
Mutual labels:  validation, form-validation, form
React Hook Form
📋 React Hooks for form state management and validation (Web + React Native)
Stars: ✭ 24,831 (+21123.08%)
Mutual labels:  validation, form-validation, form
React Final Form
🏁 High performance subscription-based form state management for React
Stars: ✭ 6,781 (+5695.73%)
Mutual labels:  validation, form-validation, form
Legit
input validation framework
Stars: ✭ 81 (-30.77%)
Mutual labels:  validation, form-validation, form
Validation
Simple PHP helper class for Validation.
Stars: ✭ 46 (-60.68%)
Mutual labels:  validation, form-validation

react-form-with-constraints

npm version Build status codecov Bundle size Prettier Airbnb Code Style

Simple form validation for React

Check the changelog for breaking changes and fixes between releases.

Introduction: what is HTML5 form validation?

⚠️ Client side validation is cosmetic, you should not rely on it to enforce security

<form>
  <label for="email">Email:</label>
  <input type="email" id="email" required>
  <button type="submit">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
  • Unobtrusive: easy to adapt regular React code
  • HTML5 error messages personalization: <FieldFeedback when="valueMissing">My custom error message</FieldFeedback>
  • Custom constraints: <FieldFeedback when={value => ...}>
  • Warnings and infos: <FieldFeedback ... warning>, <FieldFeedback ... info>
  • Async validation
  • No dependency beside React (no Redux, MobX...)
  • Re-render only what's necessary
  • Easily extendable
  • Bootstrap 4 styling with npm package react-form-with-constraints-bootstrap4
  • Material-UI integration with npm package react-form-with-constraints-material-ui
  • Support for React Native with npm package react-form-with-constraints-native
  • ...
<input type="password" name="password"
       value={this.state.password} onChange={this.handleChange}
       required pattern=".{5,}" />
<FieldFeedbacks for="password">
  <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>
</FieldFeedbacks>

Examples

How it works

The API works the same way as React Router:

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

Async support works as follow:

<FieldFeedbacks for="username">
  <Async
    promise={checkUsernameAvailability} /* Function that returns a promise */
    then={available => available ?
      <FieldFeedback key="1" info style={{color: 'green'}}>Username available</FieldFeedback> :
      <FieldFeedback key="2">Username already taken, choose another</FieldFeedback>
      // Why key=*? Needed otherwise React gets buggy when the user rapidly changes the field
    }
  />
</FieldFeedbacks>

Trigger validation:

function MyForm() {
  const form = useRef(null);

  async function handleChange({ target }) {
    // Validates only the given fields and returns Promise<Field[]>
    await form.current.validateFields(target);
  }

  async function handleSubmit(e) {
    e.preventDefault();

    // Validates the non-dirty fields and returns Promise<Field[]>
    await form.current.validateForm();

    if (form.current.isValid()) console.log('The form is valid');
    else console.log('The form is invalid');
  }

  return (
    <FormWithConstraints ref={form} onSubmit={handleSubmit} noValidate>
      <input
        name="username"
        onChange={handleChange}
        required minLength={3}
      />
      <FieldFeedbacks for="username">
        <FieldFeedback when="tooShort">Too short</FieldFeedback>
        <Async
          promise={checkUsernameAvailability}
          then={available => available ?
            <FieldFeedback key="1" info style={{color: 'green'}}>Username available</FieldFeedback> :
            <FieldFeedback key="2">Username already taken, choose another</FieldFeedback>
          }
        />
        <FieldFeedback when="*" />
      </FieldFeedbacks>
    </FormWithConstraints>
  );
}

Important note:

If a field (i.e an <input>) does not have a matching FieldFeedbacks, the library won't known about this field (and thus won't perform validation). The field name should match FieldFeedbacks.for:

<input name="MY_FIELD" ...>
<FieldFeedbacks for="MY_FIELD">
  ...
</FieldFeedbacks>


  • FieldFeedbacks

    • for: string => reference to a name attribute (e.g <input name="username">), should be unique to the current form
    • stop?: 'first' | 'first-error' | 'first-warning' | 'first-info' | 'no' => when to stop rendering FieldFeedbacks, by default stops at the first error encountered (FieldFeedbacks order matters)

    Note: you can place FieldFeedbacks anywhere, have as many as you want for the same field, nest them, mix them with FieldFeedback... Example:

    <input name="username" ... />
    
    <FieldFeedbacks for="username" stop="first-warning">
      <FieldFeedbacks>
        <FieldFeedback ... />
        <Async ... />
        <FieldFeedbacks stop="first-info">
          ...
        </FieldFeedbacks>
      </FieldFeedbacks>
    
      <FieldFeedback ... />
      <Async ... />
    </FieldFeedbacks>
    
    <FieldFeedbacks for="username" stop="no">
      ...
    </FieldFeedbacks>
    
  • FieldFeedback

    • when?:
      • ValidityState as a string => HTML5 constraint violation name
      • '*' => matches any HTML5 constraint violation
      • 'valid' => displays the feedback only if the field is valid
      • (value: string) => boolean => custom constraint
    • error?: boolean => treats the feedback as an error (default)
    • warning?: boolean => treats the feedback as a warning
    • info?: boolean => treats the feedback as an info
    • children => what to display when the constraint matches; if missing, displays the HTML5 error message if any
  • Async<T> => Async version of FieldFeedback (similar API as react-promise)

    • promise: (value: string) => Promise<T> => a promise you want to wait for
    • pending?: React.ReactNode => runs when promise is pending
    • then?: (value: T) => React.ReactNode => runs when promise is resolved
    • catch?: (reason: any) => React.ReactNode => runs when promise is rejected
  • FormWithConstraints

    • validateFields(...inputsOrNames: Array<Input | string>): Promise<Field[]> => Should be called when a field changes, will re-render the proper FieldFeedbacks (and update the internal FieldsStore). Without arguments, all fields ($('[name]')) are validated.

    • validateFieldsWithoutFeedback(...inputsOrNames: Array<Input | string>): Promise<Field[]> => Validates only all non-dirty fields (won't re-validate fields that have been already validated with validateFields()), If you want to force re-validate all fields, use validateFields(). Might be renamed to validateNonDirtyFieldsOnly() or validateFieldsNotDirtyOnly() in the future?

    • validateForm(): Promise<Field[]> => Same as validateFieldsWithoutFeedback() without arguments, typically called before to submit the form. Might be removed in the future?

    • isValid(): boolean => should be called after validateFields(), validateFieldsWithoutFeedback() or validateForm(), indicates if the fields are valid

    • hasFeedbacks(): boolean => indicates if any of the fields have any kind of feedback

    • resetFields(...inputsOrNames: Array<Input | string>): Field[] => Resets the given fields and re-render the proper FieldFeedbacks. Without arguments, all fields ($('[name]')) are reset.

    • Field =>

      {
        name: string;
        validations: { // FieldFeedbackValidation[]
          key: number;
          type: 'error' | 'warning' | 'info' | 'whenValid';
          show: boolean | undefined;
        }[];
        isValid: () => boolean
      }
      
  • Input

    If you want to style <input>, use <Input> instead: it will add classes is-pending, has-errors, has-warnings, has-infos and/or is-valid on <input> when the field is validated.

    Example: <Input name="username" /> can generate <input name="username" class="has-errors has-warnings">

    FYI react-form-with-constraints-bootstrap4 and react-form-with-constraints-material-ui already style the fields to match their respective frameworks.

Browser support

react-form-with-constraints needs ValidityState which is supported by all modern browsers and IE 11. It also needs a polyfill such as core-js to support IE 11, see React JavaScript Environment Requirements.

You can use HTML5 attributes like type="email", required, minlength...

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

...and/or rely on when functions:

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

In the last case you will have to manage translations yourself (see SignUp example).

How to consume the npm packages?

ESNext (currently ES2018) + ES modules

Files inside lib/ (package.json "module": "lib/index.js").

A recent browser or Node.js is required or you will need to transpile the react-form-with-constraints source code using Babel (or TypeScript tsc).

Several advantages:

  • The combine use of "sideEffects": false with "module": ... generates a smaller bundle thanks to tree shaking
  • You can transpile react-form-with-constraints source code with your Babel's preset-env and Browserslist configuration

For this to work, do not exclude node_modules from your webpack configuration, example:

// webpack.config.js
module: {
  rules: [
    {
      test: /\.jsx?$/,

      //exclude: /node_modules/,
      // [Babel should not transpile core-js](https://github.com/zloirock/core-js/issues/514#issuecomment-476533317)
      exclude: /\/core-js/,

      loader: 'babel-loader'
    }
  ]
}
// babel.config.js
module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        useBuiltIns: 'entry',
        corejs: 3
      }
    ],
    '@babel/preset-react'
  ],
  plugins: []
};

ES5 + CommonJS

Classic ES5 transpilation, files inside lib-es5/ (package.json "main": "lib-es5/index.js"). No tree shaking.

UMD (Universal Module Definition) + ES5

Files inside dist/. Typical use is with <script src="react-form-with-constraints.production.min.js"> inside your index.html.

A good use case is CodePen, files are generated by Rollup.

Notes

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].