![Logo](https://raw.githubusercontent.com/cupcakearmy/formhero/master/.github/Logo.jpg) ![Version](https://badgen.net/npm/v/formhero) ![Dependencies](https://badgen.net/david/dep/cupcakearmy/formhero) ![Size Badge](https://badgen.net/bundlephobia/minzip/formhero) **Fully customisable react form utility.** ## 🌈 Features - Typescript compatible - Customizable extractor, validator, getter and setters. (More in the docs) - **0** Dependencies - Tiny **~0.7kB** - React Hooks ###### Installation ``` npm i formhero ``` ### 👁 Demos - [**_Live Web_**](https://cupcakearmy.github.io/formhero/) - [**_Live Codesandbox_**](https://codesandbox.io/embed/formhero-simple-bdcx2?expanddevtools=1&fontsize=14) - [**_Live React-Native_**](https://snack.expo.io/@cupcakearmy/useform) ### Links - [Examples](#-examples-more-here) - [Docs](#-documentation) - Contructor - [Initial State](#initial) - [Validators](#validators) - [Options](#options) - Returns - [field](#field) - [form](#form) - [errors](#errors) - [isValid](#isvalid) - [update](#update) ## 🤔 Motivation So why write yet another form utility you might ask? First off, I don't like the Formik approach. In my humble opition formik is very verbose and requires lots of boilerplate. Also does not work with hooks. [react-hook-form](https://react-hook-form.com/) is a very cool library and it is the main inspiration for formhero. It does almost everything right... typescript, no deps, small, concise. The problem that I found while using it was that 3rd party ui libs like [Ant Design](https://ant.design/) or [Fabric UI](https://developer.microsoft.com/en-us/fabric#/controls/web) do not always have the standart `onChange` or `value` props in their components. That is where react-hook-form starts falling apart. This is what formhero tries to address in the most minimalistic way possible, with as little code as needed. All in pure typescript and no deps. ## 🚀 Quickstart ```typescript import ReactDOM from 'react-dom' import { useForm } from 'formhero' const Form = () => { const { field, form } = useForm({ username: '', password: '', }) const _submit = (e: React.FormEvent) => { e.preventDefault() console.log(form) } return (
) } ``` ## 🔥 Examples [(More Here)](https://github.com/CupCakeArmy/formhero/tree/master/examples) ### Validation ```typescript const Form = () => { const { field, form, errors } = useForm( { username: '', email: '', password: '', }, { username: value => value.length > 3, email: { validator: /@/, message: 'Must contain an @', }, password: [ { validator: /[A-Z]/, message: 'Must contain an uppercase letter', }, { validator: /[\d]/, message: 'Must contain a digit', }, ], } ) return (

Errors & Validation

{errors.username && 'Must be longer than 3'} {errors.email} {errors.password}
) } ``` ### Easy Customization Often it happens that you use a specific input or framework, so the default getter, setter and extractor for the event won't cut it. No worries: formhero got you covered! ```typescript const Form = () => { const { field, form, errors } = useForm({ awesome: true, }) return (
{ e.preventDefault() console.log(form) }} >

Custom

) } ``` ## 📖 Documentation ### `useForm` ```typescript const { field, errors, update, form, isValid } = useForm(initial, validators, options) ``` ### Initial This is the base state of the form. Also the typescript types are inhered by this. ###### Example ```javascript const initial = { username: 'defaultValue', password: '', rememberMe: true, } ``` ### Validators A validator is an object that taked in either a `RegExp` or a `Function` (can be async). Optionally you can pass a message string that will be displayed instead of the default one. ###### Example: Regular Expression ```javascript const validators = { // Only contains letters. // This could also be a (also async) function that returns a boolean. username: /^[A-z]*$/, } ``` ###### Example: Function ```typescript const validators = { username: (value: string) => value.lenght > 3, } ``` ###### Example: With Object ```javascript const validators = { username: { validator: /^[A-z]*$/, message: 'My custom error message', }, } ``` ###### Example: Multiple Validators ```javascript const validators = { username: [ { validator: /^[A-z]*$/, message: 'My custom error message', }, /[\d]/, async value => value.length > 0, { validator: value => true, message: 'Some other error', }, ], } ``` ### Options Sometimes it's practical to have some different default values when using for example react-native or some other framework where the default `value`, `onChange` and `(e)=> e.target.value` do not apply. ###### Example: React Native (Method 1 - Global options) [Check the Expo Snack for a live preview](https://snack.expo.io/@cupcakearmy/useform) ```javascript import * as React from 'react' import { Text, SafeAreaView, TextInput } from 'react-native' import { useForm } from 'formhero' const initial = { username: 'i am all lowercase', } const validators = {} const options = { setter: 'value', // This is not stricly necessarry as 'value' would already be the default. getter: 'onChangeText', extractor: text => text.toLowerCase(), } export default () => { const { form, field } = useForm(initial, validators, options) return ( {form.username} ) } ``` ###### Example: React Native (Method 2 - Local overwrite) ```javascript // ... export default () => { const { form, field } = useForm({ username: 'i am all lowercase', }) return ( text.toLowerCase(), })} /> {form.username} ) } ``` ### field The `field` object is used to bind the form state to the input. ###### Example: Simple ```javascript const { field } = useForm() ``` ###### Example: With custom options All are optional. ```javascript const { field } = useForm() e.target.value })} /> ``` ## Form This is the form state that you can use when submitting the data ###### Example ```javascript const { form } = useForm(...); // ...
console.log(form)}> // ...
``` ## Errors This object contains the error messages if a field is not valid. The error message can be specified by you, otherwise it will return `Error in ${field}` ###### Example ```javascript const { errors } = useForm(...) //... {errors.username} {errors.password} ``` ## isValid `isValid` is a little simple helper that checks whether the `error` object is clear or if there are errors left. ## Update The `update` function allows you to manually change and assign the state of the form. This can be usefull when you want to reset a field or the whole form. The input must have the same type as the initial state. ###### Example ```javascript const { form, update } = useForm(...) const resetUsername = () => { update({ ...form, username: '', }) } const resetForm = () => { update({ username: '', password: '', }) } ``` ### Thanks & Attributions - Thanks for [brendanmckenzie](https://github.com/brendanmckenzie) for suggesting to change `auto` to `field`.