GithubHelp home page GithubHelp logo

zackify / validify Goto Github PK

View Code? Open in Web Editor NEW
279.0 7.0 15.0 2.95 MB

Simple-as-possible React form validation

License: MIT License

HTML 8.43% JavaScript 41.48% TypeScript 50.09%
react form form-validation form-validation-react react-native

validify's Introduction

React Validify

single dependency, simplest way to validate and manage form state with hooks in React + React Native! With full test coverage and TS support.

Contents

Install

npm install react-validify lodash

Getting Started

This api has been carefully thought out over the past year. It's been in use on multiple React websites and React Native mobile applications. Using the library is simple. Include the Form component, and wrap your input's and submit buttons.

import Input from "./input";
import Submit from "./submit";
import { Form, rules } from "react-validify";

const { required, email } = rules;

const App = () => {
  let [values, setValues] = React.useState({
    email: "test",
    nested: { test: "this is nested" },
  });

  return (
    <Form values={values} onValues={setValues}>
      <Input name="email" rules={[required, email]} />
      <Input name="name" rules={[required]} />
      <Input name="date1" rules={[greaterThanDate2]} />
      <Input name="date2" />
      <Input name="nested.test" />
      <Submit />
    </Form>
  );
};

Add useField to your own inputs inside the Form wrapper. This allows you to use the library with any type of input field. It just needs to support a handleChange handleBlur and value prop. This is the Input component you see in the first example. Don't forget to pass the field name to the hook.

import React from "react";
import { useField, FieldProps } from "react-validify";

type Props = { placeholder: string } & FieldProps;

const Input = ({ name, rules, placeholder }: Props) => {
  let { handleChange, handleBlur, value, errors } = useField({ name, rules });

  return (
    <div>
      {errors ? <p>{errors[0]}</p> : null}
      <input
        name={name}
        value={value}
        onBlur={handleBlur}
        placeholder={placeholder}
        onChange={(event) => handleChange(event.target.value)}
      />
    </div>
  );
};

Add useSubmit to trigger submitting or validating:

import React from "react";
import { useSubmit } from "react-validify";

const Submit = (props) => {
  let { canSubmit, handleSubmit } = useSubmit();

  return (
    <div
      onClick={() => handleSubmit((values) => console.log("submit!", values))}
      style={{ opacity: canSubmit ? 1 : 0.5 }}
    >
      Submit Form
    </div>
  );
};
export default Submit;

The callback passed to handleSubmit will only be triggered if validation is passing.

Create rules:

const testRule: RuleFn = (value, values) =>
  value.length > values.date2.length ? "Date can't be longer" : null;

Rules get a value and values arguments. This means you can validate an input, or validate it against other form values.

Rules are guaranteed to run on a field after the first time the field is blurred, and then any time an error is present, they will run onChange.

TypeScript Support

With TS enabled, you can create a type for your form values, like so:

type Values = {
  email: string;
  date1?: string;
  name?: string;
};

Now when we use the form, it looks like this:

let [values, setValues] = useState<Values>({
    email: 'test',
  });

  return (
    <Form
      values={values}
      onValues={setValues}
    >
      <Input name="email" rules={[required, email]}/>
    </Form>
  )
}

Contributors

Thanks goes to these wonderful people (emoji key):


Zach Silveira


Ryan Castner

This project follows the all-contributors specification. Contributions of any kind welcome!

validify's People

Contributors

audiolion avatar zackify avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

validify's Issues

Validated Form loses submit Event Listener

After adding react-validify and following instructions from Readme.md, inputs from validated form lost ability to send said form after pressing Enter key. Clicking on submit button (which calls <Form onSubmit={this.onSubmit} >) still works and all validation works as expected.

I've edited your example to present described problem: https://github.com/wojciechgabrys/react-validify-issue13

Is this a bug, or a desired effect and am I'm supposed to write custom event handler for pressing Enter key?

Values are not updated when typing

Using the provided example in the usage documentation the value in Input aren't updated when a user types.

Action

User types abc

Expected behavior

Input value equals abc and the onChange event is fired

Actual behavior

Input value is empty and the onChange event is not fired.

Tested on react 16.0.0 and 15.6.1, with library 2.0.8

See example.

onBlur validation produces undesired ui effect

easiest to demonstrate with a gif, the onBlur validation affects the click processing of the next element, so you have to click it twice to get it to trigger

image

I think the issue is that when the validation passes and the error message gets removed it shifts the element spot so the click doesn't register on the element, see this gif where I click at the top of the elements for the first two and it works the as expected and the next button doesnt because I didn't click it all the way at the top

image2

Async Validation

Hi guys, do you have plans to adding async validation? it would be nice to check if a username exist in the database for example.

Implement onValue as an alternative to onValues

Would it be possible to implement the property onValue as an alternative to onValues? I'm thinking something like this:

onValue
exposes a key and value on change, you must manage the form state by passing in values if using this. Ex: values={this.state.values} must be passed too, if using the example below)

onValue={(key, value) => this.setState(() => ([key]:value))}

Also...Thanks for a great component!

Recursive cloning of elements is missing top level element

From the examples dir the surrounding dive around the next button won't be rendered currently.

class App extends Component {
  render() {
    return (
      <div className="App">
        <Form rules={{ email: 'email|required', password: 'required|min:8' }}>
          <Input name="email" />
          <Input name="password" type="password" />
          
          <div className="surroundingDivThatWontBeRendered">
            <div
              submit
              onClick={values => console.log('if validation passes, this logs')}
            >
              Submit!
            </div>
          </div>
        </Form>
      </div>
    );
  }
}

the same:attribute validation rule not working

It seems that "same:attribute" is not working. This is due to in validateOnBlurOrChange method of FormBase you call validate with one value:
const { formErrors } = validate(
{ [name]: value },
{ [name]: rules[name] },
errorMessages,
attributeNames
);
This not allow to use another fields values for validation. The validatorjs library expect all values for evaluate multiple field conditions. So if we change the code to send all values the library works:

const { formErrors } = validate(
this.props.values, // this = FormBase instance - The idea is to send all values for correct evaluation
{ [name]: rules[name] },
errorMessages,
attributeNames
);
I hope this helps.

Can't clear value of inputs after form submit

If you try to clear fields in onClick function, your state will be cleared but visually inputs still relies on old values

this.setState({ values: { description: '', note: '', amount: '', }, })

required_if:anotherfield,value rule not working

Hi guys, i have two select elements, one for hours and another for minutes, i am doing a recipes app so the user have to select the necessary time to complete the recipe. I want to require the minutes input only if the hours input is 0 because you cant complete a recipe in 0 hours and 0 minutes :P so i am using the required_if:anotherfield,value rule to do that but it is not working, what am I doing wrong? this is my component:

import { Form } from 'react-validify';
import Input from './Input';
import Select from './Select';
import './CreateRecipe.css'
import '../../bootstrap.min.css';

class CreateRecipe extends Component {
  state = {
    timeHours: [0,1,2,3,4,5,6,7,8,9,10,
      11,12,13,14,15,16,17,18,19,20,21,22,23,24],
    timeMinutes: [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,
      21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40
      ,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59],
    difficulties: ["Easy","Medium","Hard"]
  }

  render() {
    let timeHourSelect = this.state.timeHours.map((hour, index) => (
        <option key={index} value={hour}>{hour + " hours"}</option>
    ));

    let timeMinutesSelect = this.state.timeMinutes.map((minute, index) => (
      <option key={index} value={minute}>{minute + " minutes"}</option>
  ));

    let difficulty = this.state.difficulties.map((difficulty, index) => (
      <option key={index} value={difficulty}>{difficulty}</option>
    ));

    return (
    <div className="container">
      <div className="row">
        <div className="offset-md-3 col-md-6">
        <h1 className="create-recipe__header">Create a Recipe</h1>
        <Form 
          rules={{
          recipeName:'required|min:3',
          ingredients:'required|min:3',
          description: 'required|min:10',
          timeMinute: 'required_if:timeHour,0'
          }}
          errorMessages={{
            'required.recipeName': 'You have to provide a name for the recipe',
            'min.recipeName': 'The name must contain at least 3 characters',
            'required.ingredients': 'You have to provide the ingredients',
            'min.ingredients': 'The ingredients must contain at least 3 characters',
            'required.description': 'You have to provide a description',
            'min.description': 'The description must contain at least 10 characters',
            'required_if.timeMinute': 'You cant prepare a recipe in 0 minutes :)'
          }}>
          <div className="form-group">
            <label for="recipeName">Recipe name</label>
            <Input className="form-control" name="recipeName" id="recipeName" placeholder="Hamburger with cheese" />
            <label for="ingredients">Ingredients</label>
            <Input className="form-control" name="ingredients" id="ingredients" placeholder="bread x2, cheese x2, tomatoe, kitchen" />
            <label for="description">Description</label>
            <Input className="form-control" name="description" id="description" placeholder="Instructions on how to do it" />
            <label for="difficulty">Difficulty</label>
            <Select className="form-control" name="difficulty"  id="difficulty">
              {difficulty}
            </Select>
            <label for="time">Time to complete</label>
            <div className="row">
            <div className="col-md-6">
            <Select className="form-control" name="timeHour" id="time" >{timeHourSelect}</Select>
            </div>
            <div className="col-md-6">
            <Select className="form-control" name="timeMinute">{timeMinutesSelect}</Select>
            </div>
            </div>
          </div>
          <div>
          <button submit className="btn btn-success">Submit <i class="fas fa-arrow-circle-right"></i></button>
          </div>
        </Form>
      </div>

      </div> 
    </div>

    )
  }
}

export default CreateRecipe;

validate dates

Hi guys, i discover react-validify yesterday and i have been playing around with it today, it is an awesome library but i have a problem, i have a Select wrapper component that takes multiple option tags with multiple years. I need the user to enter a year before 2000 so i use the rule "before:2000" but when i select option 1999 option it keeps saying to me "the select must be before 2000". I have try different rules but none seens to work.
react-validify-example

this is how my Select component looks:


const Select = ({ error, ...props }) => (
  <div className="form-group">
    <select className="form-control" {...props}>
      {props.children}
    </select>
    <span className="help-block">{error}</span>
  </div>
);

export default Select;

this is the complete form:

import React, { Component } from 'react';
import Form from 'react-validify';
import Input from './Input';
import Select from './Select';

class FormValidation extends Component {
  date = new Date();
  age = this.date.getFullYear() - 17;
  render() {
    return (
      <Form
        rules={{
          name: 'required|alpha',
          lastName: 'alpha|required',
          email: 'email|required',
          password: 'alpha_num|required|min:8',
          select: `required|before:${this.age}`
        }}
        errorMessages={{
          'alpha.name': 'your name should not have numbers in it',
          'alpha.lastName': 'your last name should not have numbers in it',
          'required.email': 'please enter a email',
          'email.email': 'the email you entered is invalid',
          'min.password': 'Your password should have at least 8 characters',
          'alpha_num.password':
            'Your password should have alpha numeric characters',
          'required.name': 'your name is required',
          'required.lastName': 'your last name is required'
        }}
        className="col-md-6 col-md-offset-3"
      >
        <Input name="name" />
        <Input name="lastName" />
        <Input name="email" />
        <Input name="password" type="password" />
        <Select name="select">
          <option>1995</option>
          <option>1996</option>
          <option>1997</option>
          <option>1998</option>
          <option>1999</option>
          <option>2000</option>
          <option>2001</option>
        </Select>
        <button
          submit
          onClick={values => console.log(values)}
          className="btn btn-primary"
        >
          Submit!
        </button>
      </Form>
    );
  }
}

export default FormValidation;

thanks in advance.

default value for input is not working

Hey guys,
I am using react-validify right now, I run into a issue you guys may give a hand.
My input wrapper like this :

// Input.jsx
export default ({ error, ...props }) => (
  <div>
    <p>{error}</p>
    <input {...props} />
  </div>
);

And I am using it like the code below in another component

<Input type="text" name="title" className="form-control" ref={(title) => {this.title = title}}
                id="titleInput" value='hello there' />

This value will be clear to empty, When I use defaultValue instead of value, React will throw a error, because use both defaultValue and value on input element.

Any thought? Thx a lot!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.