2019-09-30 16:49:36 +00:00
![Logo ](./.github/Logo.jpg )
2019-09-26 19:30:28 +00:00
2019-09-26 20:05:53 +00:00
![Version ](https://badgen.net/npm/v/formhero )
![Dependencies ](https://badgen.net/david/dep/cupcakearmy/formhero )
![Size Badge ](https://badgen.net/bundlephobia/minzip/formhero )
2019-09-26 20:40:37 +00:00
**Fully customisable react form utility.**
2019-09-26 20:05:53 +00:00
2019-09-26 20:06:16 +00:00
## 🌈 Features
2019-09-26 19:30:28 +00:00
- Typescript compatible
- Customizable extractor, validator, getter and setters. (More in the docs)
2019-09-27 12:34:58 +00:00
- **0** Dependencies
2019-10-09 14:03:08 +00:00
- Tiny ** ~0.7kB**
2019-09-26 20:57:36 +00:00
- React Hooks
2019-09-26 19:30:28 +00:00
2019-10-09 13:57:02 +00:00
###### Installation
```
npm i formhero
```
### 👁 Demos
2019-09-28 17:30:04 +00:00
2019-09-28 17:51:29 +00:00
- [__*Live Web*__ ](https://cupcakearmy.github.io/formhero/ )
2019-10-04 12:27:54 +00:00
- [__*Live Codesandbox*__ ](https://codesandbox.io/embed/formhero-simple-bdcx2?expanddevtools=1&fontsize=14 )
2019-09-28 17:51:29 +00:00
- [__*Live React-Native*__ ](https://snack.expo.io/@cupcakearmy/useform )
2019-10-09 13:55:46 +00:00
2019-10-09 13:57:02 +00:00
### Links
2019-10-09 13:55:46 +00:00
2019-09-28 18:06:29 +00:00
- [Examples ](#-examples-more-here )
2019-09-28 17:31:10 +00:00
- [Docs ](#-documentation )
2019-09-28 17:30:04 +00:00
- Contructor
2019-09-28 17:31:10 +00:00
- [Initial State ](#initial )
- [Validators ](#validators )
2019-09-28 18:02:45 +00:00
- [Options ](#options )
2019-09-28 17:30:04 +00:00
- Returns
2019-09-28 17:31:10 +00:00
- [auto ](#auto )
- [form ](#form )
- [errors ](#errors )
- [isValid ](#isvalid )
- [update ](#update )
2019-09-28 17:30:04 +00:00
2019-09-27 12:33:51 +00:00
2019-09-26 19:30:28 +00:00
## 🚀 Quickstart
2019-09-26 19:31:13 +00:00
```typescript
2019-09-26 19:30:28 +00:00
import ReactDOM from 'react-dom'
import { useForm } from 'formhero'
2019-09-27 12:33:15 +00:00
const Form = () => {
const { auto, form } = useForm({
username: '',
password: '',
})
const _submit = (e: React.FormEvent) => {
e.preventDefault()
console.log(form)
}
return (
< div >
< form onSubmit = {_submit} >
< input { . . . auto ( ' username ' ) } / >
< input { . . . auto ( ' password ' ) } / >
< button type = "submit" > Go 🚀< / button >
< / form >
< / div >
)
}
```
2019-10-11 09:28:14 +00:00
## 🤔 Motivation
So why write yet another form utility you might ask? First off, I don't like the Formik approach. It's very verbose and in my humble opition very verbose. 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 or fabric ui 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.
2019-09-28 18:06:29 +00:00
## 🔥 Examples [(More Here)](https://github.com/CupCakeArmy/formhero/tree/master/examples)
2019-09-28 18:04:34 +00:00
2019-09-28 17:14:40 +00:00
### Validation
2019-09-27 12:33:15 +00:00
```typescript
2019-09-28 17:14:40 +00:00
const Form = () => {
2019-09-28 17:16:45 +00:00
const { auto, 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 (
< form >
< h1 > Errors & Validation< / h1 >
< input { . . . auto ( ' username ' ) } placeholder = "Username" / >
{errors.username & & 'Must be longer than 3'}
< input { . . . auto ( ' email ' ) } placeholder = "EMail" / >
{errors.email}
< input { . . . auto ( ' password ' ) } placeholder = "Password" type = "password" / >
{errors.password}
< / form >
)
2019-09-28 17:14:40 +00:00
}
```
2019-09-27 12:33:15 +00:00
2019-09-28 17:14:40 +00:00
### 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
2019-09-26 19:30:28 +00:00
const Form = () => {
2019-09-28 17:16:45 +00:00
const { auto, form, errors } = useForm({
awesome: true,
})
2019-09-26 19:30:28 +00:00
2019-09-28 17:16:45 +00:00
return (
< form onSubmit = {e = > {
e.preventDefault()
console.log(form)
}}>
2019-09-26 19:30:28 +00:00
2019-09-28 17:16:45 +00:00
< h1 > Custom< / h1 >
2019-09-26 19:30:28 +00:00
2019-09-28 17:16:45 +00:00
< label >
< input type = "checkbox" { . . . auto ( ' awesome ' , {
setter: 'checked',
getter: 'onChange',
extractor: (e) => e.target.checked
})} />
Is it awesome?
< / label >
2019-09-26 19:30:28 +00:00
2019-09-28 17:16:45 +00:00
< input type = "submit" / >
2019-09-28 17:14:40 +00:00
2019-09-28 17:16:45 +00:00
< / form >
)
2019-09-26 19:30:28 +00:00
}
```
2019-09-28 17:30:04 +00:00
## 📖 Documentation
2019-09-26 19:30:28 +00:00
### `useForm`
```typescript
2019-09-28 17:03:37 +00:00
const {auto, errors, update, form, isValid} = useForm(initial, validators, options)
2019-09-26 19:30:28 +00:00
```
2019-09-26 20:53:43 +00:00
### 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',
}
}
```
2019-09-28 17:19:10 +00:00
###### Example: Multiple Validators
```javascript
const validators = {
2019-09-28 17:19:48 +00:00
username: [
{
validator: /^[A-z]*$/,
message: 'My custom error message',
},
/[\d]/,
async (value) => value.length > 0,
{
validator: (value) => true,
message: 'Some other error',
}
2019-09-28 17:19:10 +00:00
]
}
```
2019-09-28 17:50:35 +00:00
### 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 )
2019-09-28 17:51:29 +00:00
```javascript
2019-09-28 17:50:35 +00:00
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, auto } = useForm(initial, validators, options);
return (
< SafeAreaView >
< TextInput
style={{ height: 40, borderColor: 'gray', borderWidth: 2 }}
{...auto('username')}
/>
< Text > {form.username}< / Text >
< / SafeAreaView >
);
};
```
###### Example: React Native (Method 2 - Local overwrite)
2019-09-28 17:51:29 +00:00
```javascript
2019-09-28 17:50:35 +00:00
// ...
export default () => {
const { form, auto } = useForm({
username: 'i am all lowercase',
});
return (
< SafeAreaView >
< TextInput
style={{ height: 40, borderColor: 'gray', borderWidth: 2 }}
{...auto('username', {
setter: 'value', // This is not stricly necessarry as 'value' would already be the default.
getter: 'onChangeText',
extractor: text => text.toLowerCase(),
})}
/>
< Text > {form.username}< / Text >
< / SafeAreaView >
);
};
```
2019-09-28 18:01:55 +00:00
### Auto
The `auto` object is used to bind the form state to the input.
###### Example: Simple
```javascript
const { auto } = useForm()
< input { . . . auto ( ' username ' ) } / >
```
###### Example: With custom options
All are optional.
```javascript
const { auto } = useForm()
< input { . . . auto ( ' username ' , {
getter: 'onChage',
setter: 'value',
extractor: (e) => e.target.value
})} />
```
## Form
This is the form state that you can use when submitting the data
###### Example
```javascript
const { form } = useForm(...);
// ...
< form onSubmit = {()= > console.log(form)}>
// ...
< / 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}
```
2019-09-28 18:02:45 +00:00
## isValid
2019-09-28 18:01:55 +00:00
`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: '',
})
}
```