# dry-forms

> React form validation

Latest version **1.0.2** (published 2021-10-15) · MIT license · 0 weekly downloads

## Install

```sh
npm install dry-forms
pnpm add dry-forms
yarn add dry-forms
bun add dry-forms
```

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.0.2 |
| Published | 2021-10-15 |
| First published | 2021-10-13 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 1 |
| Unpacked size | 15.6 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | Max Miroshnikov |
| Maintainers | miroshnikov |
| Keywords | validation, form, forms, form-validation, formik, react |

## Links

- npm: https://www.npmjs.com/package/dry-forms
- Repository: https://github.com/miroshnikov/dry-forms
- Issues: https://github.com/miroshnikov/dry-forms/issues
- npm.io page: https://npm.io/package/dry-forms

## Dependencies (1)

- [react](https://npm.io/package/react.md) ^17.0.2

## Alternatives

- [mobx-react](https://npm.io/package/mobx-react.md) — 2.8M weekly downloads
- [rc-tree](https://npm.io/package/rc-tree.md) — 2.6M weekly downloads
- [@react-oauth/google](https://npm.io/package/@react-oauth/google.md) — 1.3M weekly downloads
- [@wagmi/connectors](https://npm.io/package/@wagmi/connectors.md) — 877.0K weekly downloads
- [vee-validate](https://npm.io/package/vee-validate.md) — 836.4K weekly downloads

## Recent versions

- 1.0.2 (latest) — 2021-10-15
- 1.0.1 — 2021-10-15
- 1.0.0 — 2021-10-13

## README

# Dry Forms
**DryForms** is a form validation library for React.     
DryForms is a lightweight, leaner and easy-to-use alternative to Formik library that gives you more freedom in how to validate input values in a HTML form.
Though it is inspired by Formic, it takes a different, more functional approach to the process of verifying form field values. 


## Install
```sh
npm install -S dry-forms
```
```sh
yarn add dry-forms
```

## Usage
Wrap your form into a function and pass that function into `<Validate></Validate>` component. 
Below is an example component that has a simple 'subscribe' form:

### Example 1, basic validation
```typescript
import React from "react"
import { Validate } from 'dry-forms'


const required = (s: string) => s.length>0
const isEmail = (s: string) => /^[\w.%+-]+@[\w-.]+\.[\w-]{2,}$/i.test(s)

const validators = {
  name: required,
  email: [required, isEmail]
}

const initials = {name: '', email: ''}

export default function Form1() {
  return <Validate validators={validators} values={initials}>
      {(values, errors, setVal, validate) => {

          const submit = () => {
              if (validate()) {
                  console.log('submit: ', values)
              }
          }

          return <form noValidate onSubmit={e => {e.preventDefault(); submit()}}>
              <input 
                  placeholder="Your name" 
                  value={values.name} 
                  onChange={e => setVal('name', e.target.value)}
                  className={errors.includes('name') ? 'error' : ''}
              />
              <input 
                  placeholder="E-mail"
                  value={values.email} 
                  onChange={e => setVal('email', e.target.value)}
                  className={errors.includes('email') ? 'error' : ''}
              />
              <input 
                  type='submit'
                  value="Submit"
              />
          </form>
      }}
  </Validate>
}
```
Each field in the form can have a single validator or an array of validators assigned to it in the `validators` array that you pass as a property to `Validate` component.      
**Validator - is just a function!** In its simplest form it takes a value and returns `true` if the value is valid and `false` otherwise.    
When you set a new value for the field (by calling [setVal](#setval-name-string-value-any-validate-boolean--true-submitting-boolean--false-focus-boolean--false--boolean) function in the `onChange` handler) DryForms calls every validator for that field starting from the first item in the array. If a validation function returns false, field's name is added to the `errors` array and _rest of validators are not called_.     
`Validate` component also takes `values` property, that should have initial values for the form fields.    

### Example 2, messages
```typescript
import React, { createRef } from "react"
import { Validators, required, isEmail, minLength, Validate } from 'dry-forms'


const notEmpty = required('Field is mandatory')

const validators: Validators = {
    email: [notEmpty, isEmail('You entered invalid email address')],
    password: [notEmpty, minLength(8, 'Use 8 or more characters')],
    confirm: [
        notEmpty,
        (value: string, all, submitting) => {
            if (!submitting) {
                return true
            }
            const valid = value === all.password
            return {valid, ...(!valid && {message: 'Passwords do not match'})}
        }
    ]
}

const initials = {email: '', password: '', confirm: ''}

export default function Form2() {
    const formRef = createRef<HTMLFormElement>()

    return <Validate validators={validators} values={initials} form={formRef}>
        {(values, errors, setVal, validate, messages) => {

            const submit = () => {
                if (validate()) {
                    console.log('submit: ', values)
                }
            }

            return <form ref={formRef} noValidate onSubmit={e => {e.preventDefault(); submit()}}>
                <input 
                    name="email" 
                    placeholder="E-mail"
                    value={values.email} 
                    onChange={e => setVal('email', e.target.value)}
                    className={errors.includes('email') ? 'error' : ''}
                />
                {'email' in messages && messages.email.map((m,i) => <span key={i}>{m}</span>)}
                <input 
                    type='password'
                    name="password" 
                    placeholder="Password, use 8 or more characters"
                    value={values.password} 
                    onChange={e => setVal('password', e.target.value)}
                    className={errors.includes('password') ? 'error' : ''}
                />
                {'password' in messages && messages.password.map(m => <span key={m}>{m}</span>)}
                <input 
                    type='password'
                    name="confirm" 
                    placeholder="Confirm password"
                    value={values.confirm} 
                    onChange={e => setVal('confirm', e.target.value)}
                    className={errors.includes('confirm') ? 'error' : ''}
                />
                {'confirm' in messages && messages.confirm.map(m => <span key={m}>{m}</span>)}
                <input 
                    type='submit'
                    value="Submit"
                />
            </form>
        }}
    </Validate>
}
```


## API Reference

### Validate component
```typescript
<Validate validators=...  values=... form=...>
</Validate>
```
#### validators: Record<string, Validator|Validator[]>
```typescript
  type Validator = (value: any, all: Record<string, any>, sibmitting: boolean) => boolean|ValidationResult
  interface ValidationResult {
    valid: boolean
    value?: any
    message?: string
  }
```
* **value** - a new value to validate
* **all** - read-only collection of all values 
* **sibmitting** - whether it was called in the process of 'final' validation (e.g. in `onSubmit` handler), [validate()](#validate-dryrun-boolean--false--boolean) sets this to `true`

#### values: Record<string, any>
initial fields' values

#### form: React.RefObject< HTMLElement >
optional reference to the HTML form element. If passed, first input element with invalid value will receive focus after calling [validate()](#validate-dryrun-boolean--false--boolean)

### Validate child/render function
```typescript
<Validate >
{
  (values, errors, setVal, validate) => { /* ... */ }
}
</Validate>
```
#### values: Record<string, any>
Current field values.

#### errors: string[]
Array of failed field names.

#### setVal: (name: string, value: any, validate?: boolean = true, submitting?: boolean = false, focus?: boolean = false) => boolean
Function that sets the value for a field and optionally runs validation.
* **name** - field's name
* **value** - new field value
* **validate** - `true` to set a new value and validate it or `false` to update a value without validation
* **submitting** - if it was called in [validate()](#validate-dryrun-boolean--false--boolean) presumably during submitting process
* **focus** - `true` to try to set focus on input element

#### validate: (dryRun?: boolean = false) => boolean
Validate all fields, returns `true` if all values were sucessfully validated. The best place to call it in your `onSubmit` handler, e.g.
```typescript
onSubmit() {
  if (validate()) {
     // values are valid, it is OK to call fetch(...) etc.
  }
}
```
* **dryRun** - do validation in a stealthy way, i.e. without adding errors and messages
```typescript
...
<input 
  type='submit'
  value="Submit"
  disabled={!validate(true)} // <- check if valid but don't tell user about errors
/>
```

---
_Source: https://npm.io/package/dry-forms · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
