0.5.4 • Published 6 years ago

react-validable v0.5.4

Weekly downloads
2
License
MIT
Repository
github
Last release
6 years ago

react-validable

==============

npm Version License bitHound Overall Score Codecov

Simple configless validation for React. Only simple High-Ordered Components and rules.

No field configuration needed!

Installation

$ npm install react-validable  --save

Testing

Go to project folder and run

$ npm install
$ npm test

Usage Guide

See exampes here https://sick-sad-world.github.io/react-validable/

Step One - Make field suitable for validation

You may take whatever form input component you have. After being wrapped by Validable.Element it recieve props listed in table below. If you pass props with same names they will be overritten

Props injected to Child Component

  • valid - represents current validation state true if valid. Array[String] of messages otherwise.
  • pristine - Boolean - Determine whatever field was touched or not. Most of time it equals false (Scope - Elemnt) Global form pristine state you manage by our own
  • validate - function(val, opts) Function given to check whatever new value is valid.

Validate function usage

Syntax validate(value, options).

Params:

  • value - value to check validation
  • options - Array[Object] Options to override. Should be an array of 1 to n items.

Note options will be passed in the order as rules defined in Validable.Element HOC. So if you have Validable.Element(['required', 'numeric']) options [{message: 'Required'}, {message: 'Numeric'}] will be passed accordinately. If you need to update options only for numeric you should use something like this [null, {message: 'Numeric'}]

Note Dosen't matter how and when you call validate method it changes global Validable.Form state through context. You can pass result in onChange handler or onBlur and build whatever interaction you want. Read more for details.

export default function TextInput({ label, type, name, value, validate, valid, pristine, onChange, ...props }) {

  // Check file validation
  const invalid = Array.isArray(valid);

  // Define change handler 
  const changeHandler = (e) => {
    onChange(
      { [name]: e.target.value },
      validate(
        // Value to check
        e.target.value, 
        // You can change options here like message or validation specific ones 
        [{message: 'Required message'}, {message: 'Numeric message'}] 
      ) 
    );
  };

  // Set class if field is invalid and was changed
  const className = `row ${(invalid && !pristine) ? 'invalid' : ''}`;

  // Show message if field is invalid and was changed
  const message = (invalid && !pristine) ? <span>{valid.join(', ')}</span> : null;

  return (
    <div className={className}>

      <label htmlFor={`id-${name}`}>{label}</label>

      <input
        id={`id-${name}`}
        type={type}
        name={name}
        value={value || ''} 
        onChange={changeHandler}
        {...props}
      />

      {message}
    </div>
  );
}

Step Two - Create fields with validation

  • Import Validable.Element hoc
  • Wrap your input and define rules
  • Use it in form

Validation rule syntax

import Validable from 'react-validable';
// or
import { Element } from 'react-validable';

// Simple one-rule validation w/o options
// If you want declare one rule with default options
const NameInput = Validable.Element('required')(YourAwesomeInput);

// Simple one-rule validation with options
// If you want declare one rule with default options
const TextInput = Validable.Element({
  type: 'maxLength',                              // pick rule 
  treshold: 100,                                  // provide option required by rule
  message: 'Text should be less than 100 symbols' // Customize message
})(YourAwesomeInput);

// You may pass any number of rules in array in any form
const ZipCodeInput = Validable.Element(['required', {
  type: 'maxLength',                              // pick rule 
  treshold: 6,                                    // provide option required by rule
  message: 'Text should be less than 100 symbols' // Customize message
}])(YourAwesomeInput);

// You can cache settings as it presumed in React-Redux connect method and use preset for multiple inputs

const RequiredDecimal = Validable.Element(['required', 'decimal']);

const Input1 = RequiredDecimal(YourAwesomeInput);
const Input2 = RequiredDecimal(YourAwesomeInput);
const Input3 = RequiredDecimal(YourAwesomeInput);

// Somewhere inside your form component
// ======================================================================
render() {
  return (
    <form>
      <NameInput name='name' value={value} onChange={this.onChange}>
      <TextInput name='text' value={value} onChange={this.onChange}>
      <ZipCodeInput name='zip' value={value} onChange={this.onChange}>
    </form>
  )
}

Connect inputs together

Common case: Match password fields

Create two fields with equal matchers. And provide values to opposing field.

// Field one
const Pass1 = Validable.Element('equal')(Field);

// Retype password
const Pass2 = Validable.Element('equal')(Field);

// Somewhere in form
render() {
  <form>
    <Pass1 value={pass1} match={pass1}/>
    <Pass2 value={pass2} match={pass2}/>
  </form>
}

// In input fields
class Field extends React.Component {
  componentWillReceiveProps(nextProps) {
    // To handle change of other input you may use lifecycle hooks
    if (this.props.match !== newProps.match) {
      // Compare current value with new match
      this.props.validate(this.props.value, newProps.match);
    }
  }

  onChange() {
    // You can match value with opponent value on change or blur or whatever you want
    this.props.validate(this.props.value, [{math: this.props.match}]);
  }
  render() {
    <input type='password' onChange={this.onChange} value={this.props.value} />
  }
}

Options flow.

You have number of possibilities to define options

Here they is given in order. Bottom one may override upper one.

  • in validator (When you create your own custom Validator)
  • while using Validable.Element HOC where you define rules
  • right in validate function call inside input

Part Three - Put Your validation All-Together

To get results of validation in cetralized manner Validable.Form HOC provided

How to use it:

  • Create your form component
  • Make sure Form accepts valid property as Boolean
  • You can get whole validation state by passing exposeRaw={true} to your Form component
  • You can control validation state from outside using onValidation={Function} property
  import Validable from 'react-validable';
  // or
  import { Form } from 'react-validable';

  class AwesomeForm extends React.Component {
    onSubmit(e) {
      e.preventDefault();
      if (this.props.valid) {
        // Do something
      }
    }
    render() {
      // This will be full validation state copy. if [exposeRaw] is passed
      const { validationState } = this.props;

      return (
        <form onSubmit={this.onSubmit}>{Some form stuff}</form>
      )
    }
  }

  export default Validable.Form(AwesomeForm);

  // Use it somewhere
  <AwesomeForm
    exposeRaw={true} // Get whole validation state
    onValidation={someOutsideCallback(valid = Bool, state = Object)} // Get validation from outside
  />

Note! You may use Validable.Element WITHOUT Validable.Form but then you need to manage whole validation state by your own with validate method return values, or through defining your own updatePosition context handler with this signature function({ key: inputId, valid: bool or [message]})

Part Four - Validation rules list

message - validation error message - common for ALL rules

NameOpionsDescription
requirednoneCheck if value is not null or undefined
matchpattern - RegExp to matchMatch value to given RegExp
numericnoneCheck if value is number
floatnoneCheck if value is float
urlnoneCheck if value is valid URL adderss
emailnoneCheck if value is valid email address
maxLengthtreshold - Number string lenght limitCheck if value is string length less than limit
oneOfpossible - Array choises to matchCheck if value matches one of given options
filesize - Number max sie in Kbstype - String or Array[String] - mime-types acceptable by inputSpecialized validator for file type inputs. Can check file size and mime-type.

Note in rule not found Validable.Element will throw an Error. You may add new rules via method described below

Part Five - Add new Validation rule via addRule

Extends global rules object with given rules

  import Validable from 'react-validable';
  // or
  import { addRules } from 'react-validable';

  Validable.addRules({
    customRule: (value, {message, opt1, opt2, ...opts}) => {
      if (valid) {
        // Validator should return [true] if value is valid
        return true;
      } else {
        // Or text message if something wrong
        return 'Some message';
      }
    }
  })

Now you can use custom rule.

  // And use it 
  Validabe.Element(['required', 'customRule'])(SomeInput);
  // or with options
  Validabe.Element(['required', {
    rule: 'customRule',
    opt1: 'bar',
    opt2: 'foo'
  }])(SomeInput);

Licence

This project is licensed under the MIT License - see the LICENSE.md file for details

0.5.4

6 years ago

0.5.1

7 years ago

0.5.3

7 years ago

0.5.2

7 years ago

0.5.0

7 years ago