easy-react-form v2.2.6
easy-react-form
Simple, fast and easy-to-use React Form.
Install
npm install easy-react-form --saveUse
- Create a
<Form/>element withonSubmitproperty being a function ofvalues. - Put several
<Field/>s inside the<Form/>each one having anameand acomponent. - Put a submit button inside the
<Form/>.
Simplest example:
import { Form, Field } from 'easy-react-form'
<Form onSubmit={ async (values) => console.log(values) }>
<Field
name="phone"
component="input"
type="tel"
placeholder="Enter phone number" />
<button> Submit </button>
</Form>Advanced example:
import { Form, Field, Submit } from 'easy-react-form'
function AdvancedExample({ user }) {
// Form field validation example.
// If `validate` returns a string
// then it becomes the `error` of the `<Field/>`.
const validatePhone = (value) => {
if (!isValidPhoneNumber(value)) {
return 'Invalid phone number'
}
}
// Form submit function.
// Can be `async/await`.
// Can return a `Promise`.
const onSubmit = async (values) => {
console.log(values)
await new Promise(resolve => setTimeout(resolve, 3000))
}
return (
<Form onSubmit={ onSubmit }>
<Field
required
name="phone"
component={ TextInput }
type="tel"
placeholder="Enter phone number"
// Initial value for this field.
value={ user.phone }
validate={ validatePhone } />
<Submit component={ SubmitButton }>
Save
</Submit>
</Form>
)
}
// `error` is passed if the field is invalid.
function TextInput({ error, ...rest }) {
return (
<div>
<input type="text" {...rest}/>
{error &&
<div className="error">{error}</div>
}
</div>
)
}
// `wait` is `true` while form is submitting.
function SubmitButton({ wait, children }) {
return (
<button disabled={ wait }>
{ children }
</button>
)
}API
Form
The <Form/> accepts the following required properties:
onSubmit : Function(values)— Can beasyncor return aPromise.
The <Form/> accepts the following optional properties:
values : object— The initial values for this form's fields.trim : Boolean– By default, the form trims string field values when passing them toonSubmit()function. To disable this feature, settrimproperty tofalse(defaults totrue). Regardless of thetrimsetting, empty string field values are converted tonulls when passed toonSubmit()function.requiredMessage : String– The defaulterrormessage for<Field required/>. Is"Required"by default.onError : Function(Error)— Submit error handler. E.g. can show a popup with error message.autoFocus : Boolean— Set totrueto automatically focus on the first form field when the form is mounted. Defauls tofalse.initialState : object— One can pass a previously stored form state in order to restore the form to the state it was at that point in time.onStateDidChange(newState : object)— Will get called whenever a form's state has changed.- There's no
prevState : object?argument currently because the state object is mutated "in place" instead of creating an "immutable" copy of it every time it changes.
- There's no
onBeforeSubmit : FunctiononAfterSubmit : FunctiononAbandon : Function(fieldName, fieldValue)— If a form field was focused but then the form wasn't submitted and was unmounted then this function is called meaning that the user possibly tried to fill out the form but then decided to move on for some reason (e.g. didn't know what to enter in a particular form field).
ref
The <Form/> component instance (ref) provides the following methods:
focus(fieldName : String)— Focuses on a field.scroll(fieldName : String)— Scrolls to a field (if it's not visible on the screen).clear(fieldName : String)— Clears field value.get(fieldName : String)— Gets form field value.set(fieldName : String, value : any)— Sets form field value.watch(fieldName : String) : any— Watches a form field's value. Returns the current form field's value and re-renders the whole form whenever that value changes.values : object?— An object containing all form field values. Isundefineduntil the form has mounted.getElement(fieldName? : String) : Element— Returns the DOM Element for a field. If no field is specified, returns the DOM Element for the<form/>itself.reset()— Resets all form field values.
Upon form submission, if any one of its fields is invalid, then that field will be automatically scrolled to and focused, and the actual form submission won't happen.
children
The <Form/> can also accept children being a function(parameters) returning a React.Element that will be called on any form value change, so it can be used in cases when re-rendering the whole <Form/> is required on any form value change. Available parameters:
values : Object— Form values. Isundefineduntil the form is initialized (mounted) (<Field/>values areundefineduntil those<Feild/>s are mounted).set(fieldName : String, value : any)— Sets form field value.clear(fieldName : String)— Clears field value.reset()— Resets all form field values.watch(fieldName : String) : any— "Watches" a form field's value: always returns the current value of the form field and also causes a re-render of the whole form whenever that value changes. Returnsundefineduntil the form is initialized (mounted), because<Field/>s' default values are not set until those<Feild/>s have mounted.focus(fieldName : String)— Focuses on a field.scroll(fieldName : String)— Scrolls to a field (if it's not visible on the screen).submitting : boolean— Whether the form is currently being submitted.
<Form ...>
{({ values }) => {
const validateOne = (oneValue) => {
if (oneValue !== values.two) {
return 'The input values must be identical'
}
}
const validateTwo = (twoValue) => {
if (values.one !== twoValue) {
return 'The input values must be identical'
}
}
return (
<Field name="one" validate={validateOne} />
<Field name="two" validate={validateTwo} />
)
}}
</Form>useWatch()
useWatch() hook returns the watch() function.
useFormState()
useFormState() hook returns the entire state of the <Form/>:
fields: object<number?>— An object containing field "counters" (integers). When a field is no longer rendered in a form, its counter becomes0. Until a field is mounted, its counter value isundefined.values: object<any?>— An object containing field values. Fieldnames are keys. Until a field is mounted, its value isundefined.initialValues: object<any?>— An object containing field initial values. Fieldnames are keys.errors: object<string?>— An object containing field error messages. Fieldnames are keys. Until a field is mounted, its error isundefined.latestFocusedField?: string— Thenameof the latest focused field.submitting: boolean— Whether the form is being submitted.submitAttempted: boolean— Whether the form submission has been attempted by the user.
Field
<Field/> accepts the following required properties:
name : Stringcomponent : (React.Component|Function|String)— React component (can also be a string likeinput). Must accept areffor callingref.current.focus()and also must provide the means of obtaining the DOM Element for callingelement.scrollIntoView(). Therefore,componentmust be either astring, or aReact.Component, or a "functional" component wrapped inReact.forwardRef(), or a "functional" component usinguseImperativeRef()"hook" providing.focus()and.getDOMNode()methods.
<Field/> accepts the following optional properties:
value- the initial value of the field.- When both
<Field name="fieldName" value={...}/>and<Form values={{ fieldName: ... }}/>are provided, thevalueproperty of the<Field/>overrides the field's value in thevaluesobject. This makes it more of a "specific initial value" rather than "default initial value". So it can't be used, for example, to set a checkbox'es "default" value tofalse(rather thannull) because it would always befalseeven when different<Form values={...}/>are provided.
- When both
defaultValue- the default initial value of the field.- Basically, same as the
valueproperty but with one difference: it doesn't override<Form values={...}/>, which makes it suitable for cases like setting a checkbox'es "default" initial value tofalse(rather thannull).
- Basically, same as the
validate(value) : String?— Form field value validation function. Is only called whenvalueis not "empty":null/undefined/""/[]. Should return an error message if the field value is invalid.required : String or Boolean— adds "this field is required" validation for the<Field/>with theerrormessage equal torequiredproperty value if it's aStringdefaulting to"Required"otherwise. Note thatvalue: falseis considered a valid value even in case ofrequired: truebecausefalseis not an "empty" value (for example, consider a "Yes"/"No" dropdown). For that reason, iffalseshould be considered an invalid value (e.g. for a checkbox) then usevalidatefunction instead ofrequired: truefor such validation.
<Field/> passes the following properties to the field component:
valueonChangeonFocusonBlurwait : Boolean— istruewhen form is submitting.required : Boolean— istruewhen the<Field/>isrequiredand the value is missing.error : String— error message.All other properties are passed through.
The error display algorithm is as follows:
Initially, if
validate()returns an error for a field's defaultvalue, thaterroris shown.Whenever the user submits the form,
errors are displayed for all invalid form fields.Whenever the user edits a field's value,
errorbecomesundefinedfor that field while the user is focused on the field.Whenever the user focuses out of a field it is re-validated and
erroris passed if it's invalid.By default,
requirederrors are only displayed after the user has attempted submitting the form.
Therefore, the error message is only shown when the user is not editing the field. For example, while the user is typing a phone number that phone number is invalid until the used inputs it fully, but it wouldn't make sense to show the "Invalid phone number" error to the user while he is in the process of inputting the phone number (it would just be an annoying distraction).
Submit
<Submit/> accepts the following required properties:
component : (React.Component|Function|String)— React component (can also be a string likebutton).
<Submit/> passes the following properties to the component:
wait : Boolean— indicates if the form is currently being submitted.All other properties are passed through.
function Example() {
return (
<Form onSubmit={ ... }>
<Field name="text" component={ Input } />
<Submit component={ SubmitButton }>
Submit
</Submit>
</Form>
)
}
function SubmitButton({ wait, children }) {
return (
<button disabled={ wait }>
{ wait && <Spinner/> }
{ children }
</button>
)
}Lists
Sometimes there're forms on which new rows can be added by clicking "Add new row" button. For such cases there's <List/> component that handles adding new rows and removing existing ones.
import React from 'react'
import { Form, Field, List, Submit } from 'easy-react-form'
export default function Page() {
return (
<Form onSubmit={...}>
<h1>
The list of employees
</h1>
<List name="employees">
{(items) => (
<div>
{items.map((item, i) => (
<div key={item}>
<Field
item={item}
name="firstName"
.../>
<Field
item={item}
name="lastName"
.../>
<button type="button" onClick={() => items.remove(item)}>
Remove
</button>
</div>
))}
<button type="button" onClick={() => items.add()}>
Add
</button>
</div>
)}
</List>
<Submit component="button">
Save
</Submit>
</Form>
)
}<List/> accepts properties:
name: String— (required) The name of the array property in formvalues.count: Number— The initial size of the list. Is1by default, meaning that initially there will be1item in the list.children: Function— (required) A function that receives anitemsobject and returns aReact.Element. Theitemsobject provides functions:map(Function)— Maps each item to aReact.Element. The argument should be a mapping function:(item: any, i: number) => React.Element.add()— Appends a new item.remove(item: any)— Removes a given item.reset()— Resets the whole list.
Nested <List/>s are not supported.
License
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
5 years ago
5 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago