![Oracle Drags Its Feet in the JavaScript Trademark Dispute](https://cdn.sanity.io/images/cgdhsj6q/production/919c3b22c24f93884c548d60cbb338e819ff2435-1024x1024.webp?w=400&fit=max&auto=format)
Security News
Oracle Drags Its Feet in the JavaScript Trademark Dispute
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
react-form-ali
Advanced tools
A fast, lightweight, opinionated table and datagrid built on React-Form
React Form is a lightweight framework and utility for building powerful forms in React applications.
$ npm install react-form-ali
What does React-Form look like? This is the shortest and most concise example we could think of. Looking for more detail? Dive deep with the Annotated Demo Example
import React from 'react'
import { Form, Text } from 'react-form'
const MyForm = Form({
validate: ({ name }) => {
return {
name: !name ? 'A name is required' : undefined
}
},
})(({submitForm}) => {
return (
<form onSubmit={submitForm}>
<Text field='name' />
<button type='submit'>Submit</button>
</form>
)
})
export default () => {
return (
<MyForm
onSubmit={(values) => {
console.log('Success!', values)
}}
/>
)
}
This is an annotated example of the demo, demonstrating a majority of React-Form's features.
import React from 'react'
import { Form, Text, Select, Textarea, Checkbox, Radio, NestedForm, FormError } from 'react-form'
// To create a new form, simply call `Form(config)(component)`
const MyForm = Form({
// This is our config for the form. Think of it as the default props for your Form :)
// Let's give the form some hard-coded default values
defaultValues: {
friends: []
},
// Validating your form is super easy, just use the `validate` life-cycle method
validate: values => {
const { name, hobby, status, friends, address } = values
return {
name: !name ? 'A name is required' : undefined,
hobby: (hobby && hobby.length < 5) ? 'Your hobby must be at least 5 characters long' : false,
status: !status ? 'A status is required' : null,
friends: (!friends || !friends.length) ? 'You need at least one friend!' : friends.map(friend => {
const { name, relationship } = friend
return {
name: !name ? 'A name is required' : undefined,
relationship: !relationship ? 'A relationship is required' : undefined
}
}),
address: !address ? 'A valid address is required' : 0
}
},
// `onValidationFail` is another handy form life-cycle method
onValidationFail () {
window.alert('There is something wrong with your form! Please check for any required values and try again :)')
}
})(({ values, submitForm, addValue, removeValue, getError, setValue }) => {
// This is a stateless component, but you can use any valid react component to render your form.
// Forms also supply plenty of useful props for your components to utilize. See the docs for a complete list.
return (
// When the form is submitted, call the `sumbitForm` callback prop
<form onSubmit={submitForm}>
<div>
<h6>Full Name</h6>
<Text // This is the built-in Text formInput
field='name' // field is a string version of the field location
placeholder='Your name' // all other props are sent through to the underlying component, in this case an <input />
onChange={(value) => { // it needs to call setState to apply the text field changes
// capitalize first letter
if (value.length > 0) {
setValue('name', value.charAt(0).toUpperCase() + value.slice(1))
} else {
setValue('name', value)
}
}}
/>
</div>
<div>
<h6>Relationship Status</h6>
<Select // This is the built-in Select formInput
field='status'
options={[{ // You can ship it some options like usual
label: 'Single',
value: 'single'
}, {
label: 'In a Relationship',
value: 'relationship'
}, {
label: 'It\'s Complicated',
value: 'complicated'
}]}
/>
</div>
<div>
<h6>Short Bio</h6>
<Textarea // This is the built-in Textarea formInput
field='bio'
placeholder='Short Bio'
/>
</div>
{/* Arrays in forms are super easy to handle */}
<h6>Friends</h6>
{/* This is a custom form error for the root of the friends list (see validation function) */}
<FormError field='friends' />
<div className='nested'>
{!values.friends.length ? (
<em>No friends have been added yet</em>
) : values.friends.map((friends, i) => ( // Loop over the values however you'd like
<div key={i}>
<div>
<h6>Full Name</h6>
<Text
field={['friends', i, 'name']} // You can easily pass an array-style field path. Perfect for passing down as props or nested values
placeholder='Friend Name'
/>
</div>
<div>
<h6>Relationship</h6>
<Select
field={`friends.${i}.relationship`} // If you don't like arrays, you can also use a string template
options={[{
label: 'Friend',
value: 'friend'
}, {
label: 'Acquaintance',
value: 'acquaintance'
}, {
label: 'Colleague',
value: 'colleague'
}]}
/>
</div>
<button // This button will remove this friend from the `friends` field
type='button'
onClick={() => removeValue('friends', i)} // `removeValue` takes a field location for an array, and the index for the item to remove
>
Remove Friend
</button>
</div>
))}
</div>
<div>
<button // This button will add a new blank friend item to the `friends` field
type='button'
onClick={() => addValue('friends', {})} // `addValue` takes an array-like field, and the value to add
>
Add Friend
</button>
</div>
<div>
<h6>Address</h6>
{/* An address has a couple of parts to it, and will probably have its own validation function. */}
{/* Let's make it reusable by using a nested form */}
<NestedForm
form={AddressForm} // This is just another form that we built below
field='address' // The results of this nested form will be set to this field value on this form.
/>
</div>
<div>
<label>
<Checkbox // This is the built-in checkbox formInput
field='createAccount'
/>
<span>Create Account?</span>
</label>
</div>
<div>
<h6>Notify me via</h6>
<radiogroup>
<label>
<Radio // This is the built-in radio formInput
field='notificationType'
value='email' // This is the value the field will be set to when this radio button is active
/>
<span>Email</span>
</label>
<label>
<Radio
field='notificationType'
value='text'
/>
<span>Text</span>
</label>
<label>
<Radio
field='notificationType'
value='phone'
/>
<span>Phone</span>
</label>
</radiogroup>
</div>
<br />
<br />
{/* // Since this is the parent form, let's put a submit button in there ;) */}
{/* // You can submit your form however you want, as long as you call the `submitForm` callback */}
<button>
Submit
</button>
</form>
)
})
// This is our reusable address form
const AddressForm = Form({
// It can have its own validation function!
validate: values => {
return {
street: !values.street ? 'A street is required' : undefined,
city: !values.city ? 'A city is required' : undefined,
state: !values.state ? 'A state is required' : undefined
}
}
})(() => {
return (
<div>
<Text
field='street'
placeholder='Street'
/>
<br />
<Text
field='city'
placeholder='City'
/>
<br />
<Text
field='state'
placeholder='State'
/>
</div>
)
})
export default () => {
return (
<div>
<div className='table-wrap'>
<MyForm
onSubmit={(values) => {
window.alert(JSON.stringify(values, null, 2))
}}
// For more available props, see the docs!
/>
</div>
</div>
)
}
Creating custom form inputs is extremely simple. This is a quick example of how to wrap the React-Select component:
// formReactSelect.js
import React from 'react'
import { FormInput } from 'react-form'
import Select from 'react-select'
export default ({field, ...rest}) => {
return (
<FormInput field={field}> // Use FormInput with a fieldName to get the field's api
// FormInput's only child should be a function that provides you the field api and returns valid jsx or a react component
{({ setValue, getValue, setTouched }) => {
return (
<Select
{...rest} // Send the rest of your props to React-Select
value={getValue()} // Set the value to the forms value
onChange={val => setValue(val)} // On Change, update the form value
onBlur={() => setTouched()} // And the same goes for touched
/>
)
}}
</FormInput>
)
}
// Now you can use it in a form!
import React from 'react'
import FormReactSelect from './formReactSelect'
Form()(() => {
return (
<FormReactSelect
field='my.field'
clearable={false}
options={[...]}
/>
)
})
Form(defaultPropsAndLifecycleMethods)(component)
Example
import { Form } from 'react-form'
// Create a new form by passing `Form` any default props and/or lifecycle methods
const myForm = Form({
validate () {...},
})(validReactComponent)) // Then pass in any valid react component, component class or stateless component
The form lifecycle is what makes React-Form tick, so naturally you can configure just about anything in react-form to your needs through these lifecycle methods.
You can define form props and lifecycle methods at 3 different levels:
FormDefaultProps
(See {FormDefaultProps})defaultProps
to Form
Here is a list of all available properties and lifecycle methods that React-Form uses:
Form({
defaultValues: {
name: 'Tanner Linsley'
hobby: 'javascript'
}
})(component)
loadState
is called. If a saved form state object is returned, it will hydrate the form state from this object.Form({
preValidate: (values) => {
values.hobby = values.hobby.substring(0, 6) // Constantly scrub the hobby field to never be more than 6 characters long
return values
}
})(component)
validate
returns any errors, setAllTouched(true)
will automatically be called on the form. Likewise, if the form has been marked as globally dirty, and no errors are returned, setAllTouched(false)
will automatically clear the global dirty stateForm({
validate: ({name, password}) => {
return {
name: !name ? 'A name is required' : null,
password: (!password || password.length < 6) ? 'A password of 6 or more characters is required' : null
}
}
})(component)
values
changeinitial
is set to true, this indicates that the component just mounted and is firing onChange
for the first time (this is utilized by nested forms)state
is changed.onSubmit
method.Form({
preSubmit: (values) => {
values.hobby = values.hobby.toLowerCase() // Scrub the hobby field to be lowercase on submit
return values
}
})(component)
submitForm
, this method will be called with the values of the parent form.// Per Instance (usually this way)
const example = (
<MyForm
onSubmit={(values) => {
console.log('Form Submitted with these values:', values)
}}
/>
)
// Per Form
Form({
onSubmit: (values) => {
console.log('Form Submitted with these values:', values)
}
})(component)
submitForm
, this method will be called.Form({
postSubmit: (values) => {
console.log('Success!', values)
}
})(component)
defaultProps
will function as hardcoded defaultProps. They will be available on the componentused to render the form unless overridden by a prop passed tot he instanceAll of the following props are available on the component used to render your form
Note: If a prop of the same name is passed to the form instance, it will override these props below.
Form()(
({values}) => {
console.log(values)
// {
// name: 'Tanner Linsley',
// hobby: 'Javascript',
// nestedForm: {
// notes: 'These are some notes from a nested form'
// }
// }
}
)
FormInput
or using the FieldError
component.validate
lifecycle methodnull
Form()(
({errors}) => {
console.log(errors)
// {
// name: 'Name is required and must be at least 5 characters',
// hobby: 'Required',
// nestedForm: 'Requires some valid nested fields' // See "nestedErrors" section
// }
}
)
nestedErrors
is an object map indicating any nested forms that did not pass their own validationFormInput
or using the FieldError
component.nestedErrors
field will be set to true.{}
Form()(
({nestedErrors}) => {
console.log(nestedErrors)
// {
// nestedForm: true // there must be an error in the form located at the "nestedForm" field
// }
}
)
setValue()
or setTouched()
, its corresponding field location in this object is marked as true.FormInput
or using the FieldError
component.{}
Form()(
({touched}) => {
console.log(touched)
// {
// touched: { myField: true } // the `myField` field has been touched
// }
}
)
field
to value
. Usually this functionality is contained in an InputField of sorts, but it is still available on the form itself in its generic form.field
can be a string or array property location eg.
my.field.name
== ['my', 'field', 'name']
my.fields[3]
== ['my', 'fields', 3]
[['my', 'fields'], [5], 'stuff']
== my.fields[5].stuff
noTouch
is true, the touched
state of the field won't change.Form()(
({setValue}) => {
return (
<button onClick={() => setValue('some.field', true)}>
Set Some Field to TRUE
</button>
)
}
)
field
. Usually this functionality is contained in an InputField of sorts, but it is still available on the form itself in its generic form.field
can be a string or array property location eg.
my.field.name
== ['my', 'field', 'name']
my.fields[3]
== ['my', 'fields', 3]
[['my', 'fields'], [5], 'stuff']
== my.fields[5].stuff
fallback
value which will be used if the field does not exist or if its value === undefined
Form()(
({getValue}) => {
return (
<span>Current Value: {getValue('my.field')}</span>
)
}
)
field
in nestedErrors
to value
to indicate that a nested form did or did not not pass its own validation.validate
lifecycle method will be set to undefined.validate
lifecycle method.NestedForm
componentfield
. Usually this functionality is contained in an InputField of sorts, but it is still available on the form itself in its generic form.field
can be a string or array property location eg.
my.field.name
== ['my', 'field', 'name']
my.fields[3]
== ['my', 'fields', 3]
[['my', 'fields'], [5], 'stuff']
== my.fields[5].stuff
Form()(
({getError}) => {
return (
<span>Current Error: {getError('my.field')}</span>
)
}
)
field
in the touched
state to value
(which defaults to true). Usually this functionality is contained in an InputField of sorts, but it is still available on the form itself in its generic form.field
can be a string or array property location eg.
my.field.name
== ['my', 'field', 'name']
my.fields[3]
== ['my', 'fields', 3]
[['my', 'fields'], [5], 'stuff']
== my.fields[5].stuff
Form()(
({setTouched}) => {
return (
<button onClick={() => setTouched('some.field', true)}>
Set some fields touched value to TRUE
</button>
)
}
)
field
. Usually this functionality is contained in an InputField of sorts, but it is still available on the form itself in its generic form.field
can be a string or array property location eg.
my.field.name
== ['my', 'field', 'name']
my.fields[3]
== ['my', 'fields', 3]
[['my', 'fields'], [5], 'stuff']
== my.fields[5].stuff
Form()(
({getTouched}) => {
return (
<span>Current Touched: {getTouched('my.field')}</span>
)
}
)
value
into an array-like field
as a new value.field
can be a string or array property location eg.
my.field.name
== ['my', 'field', 'name']
my.fields[3]
== ['my', 'fields', 3]
[['my', 'fields'], [5], 'stuff']
== my.fields[5].stuff
Form()(
({addField}) => {
return (
<button onClick={() => addField('todos', {})}>
Add Todo
</button>
)
}
)
field
.field
can be a string or array property location eg.
my.field.name
== ['my', 'field', 'name']
my.fields[3]
== ['my', 'fields', 3]
[['my', 'fields'], [5], 'stuff']
== my.fields[5].stuff
Form()(
({removeField}) => {
return (
<div>
{todos.map((todo, i) => {
return (
<button onClick={() => removeField('todos', i)}>
Remove Todo
</button>
)
})}
</div>
)
}
)
field
.field
can be a string or array property location eg.
my.field.name
== ['my', 'field', 'name']
my.fields[3]
== ['my', 'fields', 3]
[['my', 'fields'], [5], 'stuff']
== my.fields[5].stuff
Form()(
({swapValues}) => {
return (
<div>
{todos.map((todo, i) => {
return (
<button onClick={() => swapValues('todos', i, i - 1)}>
Move Up
</button>
)
})}
</div>
)
}
)
dirty
state to !!value
(which defaults to true
). If true
, its value will override any value retrieved using getTouched
.submitForm
lifecycle method when a forms validation is failedForm()(
({setAllTouched}) => {
return (
<button onClick={setAllTouched}>
Touch / Dirty the entire form // innuendo? hmm....
</button>
)
}
)
preValidate(values, state, props)
filter your values before they are validatedvalidate(values, state, props)
validate your formonValidationFail(state, props)
handle failed validation (if applicable)preSubmit(values, state, props)
filter your values before they are successfully submittedonSubmit(values, state, props)
handle the submissionpostSubmit(values, state, props)
handle after a successful submissionconst MyForm = Form()(
({submitForm}) => {
return (
<form onSubmit={submitForm}>
<button type='submit'>Submit Form</button>
</form>
)
}
)
const usageExample = () => {
return (
<MyForm
onSubmit={(values, state, props) => {
console.log(values)
}}
/>
)
}
import { FormDefaultProps } from 'react-form'
Object.assign(FormDefaultProps, {
onValidationFail: () => { console.log('uh oh...') }
})
FormInput
must be a function that returns valid JSX. This function is passed one parameter, the form api object.field
prop is passed, every API method will be auto-bound to use that field
. Otherwise, they operate at the form-level as usual.showErrors
prop is set to false
, errors will be hiddenerrorBefore
prop is set to true
, any error will be shown before the component, instead of afterisForm
props is set to true
, the field error will only be shown if the parent form has been unsuccessfully submitted. This is normally only used for NestedForm
components to avoid unnecessary or duplicate error messages.Example - A simple wrapper for React Select
import { FormInput } from 'react-form'
import ReactSelect from 'react-select'
export default ({field, ...rest}) => {
return (
<FormInput field={field}>
{({ setValue, getValue, setTouched }) => {
return (
<ReactSelect
{...rest}
value={getValue()}
onChange={val => setValue(val)}
onBlur={() => setTouched()}
/>
)
}}
</FormInput>
)
}
Example
import { FormError } from 'react-form'
const example = (
<FormError field='my.field' />
)
###{ AddErrors }
FormField
must be a function that returns valid JSX. This function is passed one parameter, the form api object.field
prop is passed, every API method will be auto-bound to use that field. Otherwise, they operate at the form-level as usual.Example
import { FormField } from 'react-form'
function customInput ({field, ...rest}) {
return (
<FormField field={field}>
{({ setValue, getValue, setTouched }) => {
return (
<input
value={getValue()}
onChange={e => setValue(e.target.value)}
onBlur={() => setTouched()}
/>
)
}}
</FormField>
)
}
FormInput
component.field
prop to be passednoTouch
to avoid validation while the value is changingExample
import { Text, Select, Checkbox, Textarea, Radio } from 'react-form'
const example = (
<div>
<Text
field='name'
placeholder='Full name'
/>
<Select
placeholder='choose status...'
field='employed'
options={[{
label: 'Employed',
values: true
}, {
label: 'Unemployed',
value: false
}]}
/>
<Select
placeholder='choose favorite sports...'
field='sports'
options={[{
label: 'Baseball',
values: 'baseball'
}, {
label: 'Soccer',
value: 'soccer'
}]}
multiple
/>
<Checkbox
field='createAccount'
/>
<Textarea
field='notes'
placeholder='Notes'
/>
<radiogroup>
<Radio
field='notificationType'
value='email'
/>
<Radio
field='notificationType'
value='text'
/>
<Radio
field='notificationType'
value='phone'
/>
</radiogroup>
</div>
)
object
to their assigned field on their parent form.undefined
to their parent's validation function in place of the nested form's values. For instance, if a nested form using the field myNestedForm
has an error, the parent validation function might look like this: validate ({name, hobby, myNestedForm}) {
return {
// normal validation...
myNestedForm: !myNestedForm ? 'Name Required' : undefined,
}
}
<Form />
elements (which would be invalid HTML).onValidationFail
preSubmit
onSubmit
To suggest a feature, create an issue if it does not already exist. If you would like to help develop a suggested feature follow these steps:
npm install
npm watch
src/
directoryIf you would like to preview your changes, you can link and utilize the example like so:
npm link
cd example
npm install
npm link react-form
npm watch
src/screens/index.js
if neededlocalhost:8000
Also you may use react-storybooks to view changes. Feel free to add new storybooks if they don't exist yet.
npm run storybook
localhost:8085
##Credits This is a fork from https://github.com/tannerlinsley/react-form with some minor improvements
FAQs
A fast, lightweight, opinionated table and datagrid built on React-Form
The npm package react-form-ali receives a total of 1 weekly downloads. As such, react-form-ali popularity was classified as not popular.
We found that react-form-ali demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
Security News
The Linux Foundation is warning open source developers that compliance with global sanctions is mandatory, highlighting legal risks and restrictions on contributions.
Security News
Maven Central now validates Sigstore signatures, making it easier for developers to verify the provenance of Java packages.