Description
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.
formhero alternatives and similar libraries
Based on the "Form Widgets" category.
Alternatively, view formhero alternatives based on common mentions on social networks and blogs.
-
jQuery-File-Upload
DISCONTINUED. File Upload widget with multiple file selection, drag&drop support, progress bar, validation and preview images, audio and video for jQuery. Supports cross-domain, chunked and resumable file uploads. Works with any server-side platform (Google App Engine, PHP, Python, Ruby on Rails, Java, etc.) that supports standard HTML form file uploads. -
Joplin
Joplin - the privacy-focused note taking app with sync capabilities for Windows, macOS, Linux, Android and iOS. -
select2
Select2 is a jQuery based replacement for select boxes. It supports searching, remote data sets, and infinite scrolling of results. -
Sortable Β
Reorderable drag-and-drop lists for modern browsers and touch devices. No jQuery or framework required. -
dropzone
Dropzone is an easy to use drag'n'drop library. It supports image previews and shows nice progress bars. -
selectize.js
Selectize is the hybrid of a textbox and <select> box. It's jQuery based, and it has autocomplete and native-feeling keyboard navigation; useful for tagging, contact lists, etc. -
bootstrap-select
:rocket: The jQuery plugin that brings select elements into the 21st century with intuitive multiselection, searching, and much more. -
fine-uploader
DISCONTINUED. Multiple file upload plugin with progress-bar, drag-and-drop, direct-to-S3 uploading. -
plupload
Plupload is JavaScript API for building file uploaders. It supports multiple file selection, file filtering, chunked upload, client side image downsizing and when necessary can fallback to alternative runtimes, like Flash and Silverlight. -
jQuery-Autocomplete
Ajax Autocomplete for jQuery allows you to easily create autocomplete/autosuggest boxes for text input fields -
selectize.js (old)
Selectize is the hybrid of a textbox and select box. It's jQuery based and it has autocomplete and native-feeling keyboard navigation; useful for tagging, contact lists, etc. -
FileAPI
FileAPI β a set of javascript tools for working with files. Multiupload, drag'n'drop and chunked file upload. Images: crop, resize and auto orientation by EXIF. -
jQuery-Tags-Input
DISCONTINUED. Magically convert a simple text input into a cool tag list with this jQuery plugin. -
flow.js
A JavaScript library providing multiple simultaneous, stable, fault-tolerant and resumable/restartable file uploads via the HTML5 File API. -
jquery multi-select
A user-friendlier drop-in replacement for the standard select with multiple attribute activated. -
analytics
Lightweight analytics abstraction layer for tracking page views, custom events, & identifying visitors -
Garlic.js
Automatically persist your forms' text and select field values locally, until the form is submitted. -
datedropper
DISCONTINUED. datedropper is a jQuery plugin that provides a quick and easy way to manage dates for input fields. -
Duet Date Picker
DISCONTINUED. Duet Date Picker is an open source version of Duet Design Systemβs accessible date picker. Try live example at https://duetds.github.io/date-picker/ -
JavaScript-autoComplete
An extremely lightweight and powerful vanilla JavaScript completion suggester. -
Syncfusion JavaScript UI Controls
Syncfusion JavaScript UI controls library offer more than 50+ cross-browser, responsive, and lightweight HTML5 UI controls for building modern web applications. -
Amazon Autocomplete JS Plugin
π Unlock the full power of the Amazon autocompletion engine right into your search input. JavaScript Plugin. -
Ajax Bootstrap Select
This uses the bootstrap-select plugin and extends it so that you can use a remote source to search. -
HTML5 AJAX File Uploader
JavaScript library that manages file uploads using html5 drag and drop and file API's.
SaaSHub - Software Alternatives and Reviews
* Code Quality Rankings and insights are calculated and provided by Lumnify.
They vary from L1 to L5 with "L5" being the highest.
Do you think we are missing an alternative of formhero or a related project?
README
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
npm i formhero
Note: Requires at least typescript version 3.5
, otherwise the error object will not have the right inherited types.
π Demos
π Docs
- [Examples](#-examples-more-here)
- [Docs](#-documentation)
- Contructor
- Initial State
- Validators
- Options
- Returns
- field
- form
- errors
- isValid
- setField
- setForm
- setErrors
π€ Motivation & Why
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.
π Quickstart
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 (
<div>
<form onSubmit={_submit}>
<input {...field('username')} />
<input {...field('password')} />
<button type="submit">Go π</button>
</form>
</div>
)
}
π₯ Examples (More Here)
Validation
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 (
<form>
<h1>Errors & Validation</h1>
<input {...field('username')} placeholder="Username" />
{errors.username && 'Must be longer than 3'}
<input {...field('email')} placeholder="EMail" />
{errors.email}
<input {...field('password')} placeholder="Password" type="password" />
{errors.password}
</form>
)
}
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!
const Form = () => {
const { field, form, errors } = useForm({
awesome: true,
})
return (
<form
onSubmit={e => {
e.preventDefault()
console.log(form)
}}
>
<h1>Custom</h1>
<label>
<input
type="checkbox"
{...field('awesome', {
setter: 'checked',
getter: 'onChange',
extractor: e => e.target.checked,
})}
/>
Is it awesome?
</label>
<input type="submit" />
</form>
)
}
Dynamic Fields
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.
import React from "react";
import ReactDOM from "react-dom";
import { useForm } from "formhero";
type MyForm = { [field: string]: string | number };
const init: MyForm = {
username: "unicorn",
password: ""
};
const Form: React.FC = () => {
const { field, form, errors } = useForm(init);
return (
<form>
<input {...field("username")} placeholder="Username" />
<input {...field("someother")} placeholder="Something else" />
<input {...field("password")} placeholder="Password" type="password" />
</form>
);
};
π Documentation
useForm
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.
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) 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.
const validators = {
// Only contains letters.
// This could also be a (also async) function that returns a boolean.
username: /^[A-z]*$/,
}
const validators = {
username: (value: string) => value.lenght > 3,
}
const validators = {
username: {
validator: /^[A-z]*$/,
message: 'My custom error message',
},
}
const validators = {
username: [
{
validator: /^[A-z]*$/,
message: 'My custom error message',
},
/[\d]/,
async value => value.length > 0,
{
validator: value => true,
message: 'Some other error',
},
],
}
const validators = {
username: async (s: string) => {
const taken = await API.isUsernameTaken(s)
return taken ? 'Username is taken': true
}
}
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.
Check the Expo Snack for a live preview
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 (
<SafeAreaView>
<TextInput style={{ height: 40, borderColor: 'gray', borderWidth: 2 }} {...field('username')} />
<Text>{form.username}</Text>
</SafeAreaView>
)
}
// ...
export default () => {
const { form, field } = useForm({
username: 'i am all lowercase',
})
return (
<SafeAreaView>
<TextInput
style={{ height: 40, borderColor: 'gray', borderWidth: 2 }}
{...field('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>
)
}
field
The field
object is used to bind the form state to the input.
const { field } = useForm()
<input {...field('username')} />
All are optional.
const { field } = useForm()
<input {...field('username', {
getter: 'onChage',
setter: 'value',
extractor: (e) => e.target.value
})} />
Form
This is the form state that you can use when submitting the data
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}
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.
setField
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.
const { form, setField } = useForm(...)
const resetUsername = () => {
setField('username', 'new value')
}
setForm
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.
const initial = {username: '', password: ''}
const { form, setForm } = useForm(initial, ...)
const resetForm = () => {
setForm(initial)
}
setErrors
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).
const { form, setErrors } = useForm(...)
const setError = () => {
setErrors({username: 'Already taken'})
}
Thanks & Attributions
- Thanks for brendanmckenzie for suggesting to change
auto
tofield
.