Gathering detailed insights and metrics for formhero
Gathering detailed insights and metrics for formhero
Gathering detailed insights and metrics for formhero
Gathering detailed insights and metrics for formhero
@formhero/formhero-js
A project for our formhero.js integration library which enables the use for FormHero forms within a separately hosted website.
formhero-app
This is the main FormHero application
formhero-js
A project for our formhero.js integration library which enables the use for FormHero forms within a separately hosted website.
npm install formhero
Typescript
Module System
Node Version
NPM Version
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
Fully customisable react form utility.
npm i formhero
Note: Requires at least typescript version 3.5
, otherwise the error object will not have the right inherited types.
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 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.
1import ReactDOM from 'react-dom' 2import { useForm } from 'formhero' 3 4const Form = () => { 5 const { field, form } = useForm({ 6 username: '', 7 password: '', 8 }) 9 10 const _submit = (e: React.FormEvent) => { 11 e.preventDefault() 12 console.log(form) 13 } 14 15 return ( 16 <div> 17 <form onSubmit={_submit}> 18 <input {...field('username')} /> 19 <input {...field('password')} /> 20 21 <button type="submit">Go 🚀</button> 22 </form> 23 </div> 24 ) 25}
1const Form = () => { 2 const { field, form, errors } = useForm( 3 { 4 username: '', 5 email: '', 6 password: '', 7 }, 8 { 9 username: (value) => value.length > 3, 10 email: { 11 validator: /@/, 12 message: 'Must contain an @', 13 }, 14 password: [ 15 { 16 validator: /[A-Z]/, 17 message: 'Must contain an uppercase letter', 18 }, 19 { 20 validator: /[\d]/, 21 message: 'Must contain a digit', 22 }, 23 ], 24 } 25 ) 26 27 return ( 28 <form> 29 <h1>Errors & Validation</h1> 30 31 <input {...field('username')} placeholder="Username" /> 32 {errors.username && 'Must be longer than 3'} 33 34 <input {...field('email')} placeholder="EMail" /> 35 {errors.email} 36 37 <input {...field('password')} placeholder="Password" type="password" /> 38 {errors.password} 39 </form> 40 ) 41}
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!
1const Form = () => { 2 const { field, form, errors } = useForm({ 3 awesome: true, 4 }) 5 6 return ( 7 <form 8 onSubmit={(e) => { 9 e.preventDefault() 10 console.log(form) 11 }} 12 > 13 <h1>Custom</h1> 14 15 <label> 16 <input 17 type="checkbox" 18 {...field('awesome', { 19 setter: 'checked', 20 getter: 'onChange', 21 extractor: (e) => e.target.checked, 22 })} 23 /> 24 Is it awesome? 25 </label> 26 27 <input type="submit" /> 28 </form> 29 ) 30}
Sometimes you don't know all the fields upfront. You can simply define a generic type and assign it to the initial object. Of course type assistance is limited in this case as formhero cannot be sure what keys are valid.
1import React from 'react' 2import ReactDOM from 'react-dom' 3import { useForm } from 'formhero' 4 5type MyForm = { [field: string]: string | number } 6 7const init: MyForm = { 8 username: 'unicorn', 9 password: '', 10} 11 12const Form: React.FC = () => { 13 const { field, form, errors } = useForm(init) 14 15 return ( 16 <form> 17 <input {...field('username')} placeholder="Username" /> 18 <input {...field('someother')} placeholder="Something else" /> 19 <input {...field('password')} placeholder="Password" type="password" /> 20 </form> 21 ) 22}
useForm
1const { field, errors, update, form, isValid } = useForm(initial, validators, options)
This is the base state of the form. Also the typescript types are inhered by this.
1const initial = { 2 username: 'defaultValue', 3 password: '', 4 rememberMe: true, 5}
A validator is an object that taked in either a RegExp
or a Function
(can be async) or an array of those. Optionally you can pass a message string that will be displayed instead of the default one.
A validator functions takes the current value as input and should return a boolean
or a string
. If returned true
the input counts as valid, if false
it's not. If you pass a string formhero will treat it as not valid and display the string returned as error message.
1const validators = { 2 // Only contains letters. 3 // This could also be a (also async) function that returns a boolean. 4 username: /^[A-z]*$/, 5}
1const validators = { 2 username: (value: string) => value.lenght > 3, 3}
1const validators = { 2 username: { 3 validator: /^[A-z]*$/, 4 message: 'My custom error message', 5 }, 6}
1const validators = { 2 username: [ 3 { 4 validator: /^[A-z]*$/, 5 message: 'My custom error message', 6 }, 7 /[\d]/, 8 async (value) => value.length > 0, 9 { 10 validator: (value) => true, 11 message: 'Some other error', 12 }, 13 ], 14}
1const validators = { 2 username: async (s: string) => { 3 const taken = await API.isUsernameTaken(s) 4 return taken ? 'Username is taken' : true 5 }, 6}
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.
Check the Expo Snack for a live preview
1import * as React from 'react' 2import { Text, SafeAreaView, TextInput } from 'react-native' 3import { useForm } from 'formhero' 4 5const initial = { 6 username: 'i am all lowercase', 7} 8const validators = {} 9const options = { 10 setter: 'value', // This is not stricly necessarry as 'value' would already be the default. 11 getter: 'onChangeText', 12 extractor: (text) => text.toLowerCase(), 13} 14 15export default () => { 16 const { form, field } = useForm(initial, validators, options) 17 18 return ( 19 <SafeAreaView> 20 <TextInput style={{ height: 40, borderColor: 'gray', borderWidth: 2 }} {...field('username')} /> 21 <Text>{form.username}</Text> 22 </SafeAreaView> 23 ) 24}
1// ... 2 3export default () => { 4 const { form, field } = useForm({ 5 username: 'i am all lowercase', 6 }) 7 8 return ( 9 <SafeAreaView> 10 <TextInput 11 style={{ height: 40, borderColor: 'gray', borderWidth: 2 }} 12 {...field('username', { 13 setter: 'value', // This is not stricly necessarry as 'value' would already be the default. 14 getter: 'onChangeText', 15 extractor: (text) => text.toLowerCase(), 16 })} 17 /> 18 <Text>{form.username}</Text> 19 </SafeAreaView> 20 ) 21}
The field
object is used to bind the form state to the input.
1const { field } = useForm() 2 3<input {...field('username')} />
All are optional.
1const { field } = useForm() 2 3<input {...field('username', { 4 getter: 'onChage', 5 setter: 'value', 6 extractor: (e) => e.target.value 7})} />
This is the form state that you can use when submitting the data
1 2const { form } = useForm(...); 3 4// ... 5 6<form onSubmit={()=> console.log(form)}> 7 // ... 8</form>
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}
1const { errors } = useForm(...) 2 3//... 4 5{errors.username} 6{errors.password}
isValid
is a little simple helper that checks whether the error
object is clear or if there are errors left.
The setField
function allows you to manually change and assign the state of a field. The type of the field must be the same as the initial type given in the constructor.
1const { form, setField } = useForm(...) 2 3const resetUsername = () => { 4 setField('username', 'new value') 5}
The setForm
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.
1const initial = {username: '', password: ''} 2 3const { form, setForm } = useForm(initial, ...) 4 5const resetForm = () => { 6 setForm(initial) 7}
The setErrors
function allows you to manually change and assign the state of the errors. This can be usefull when you want to set an error manually (e.g. sent from the server).
1 2const { form, setErrors } = useForm(...) 3 4const setError = () => { 5 setErrors({username: 'Already taken'}) 6}
auto
to field
.No vulnerabilities found.
No security vulnerabilities found.