Validations consist of 4 parts. A name
, an isValid
function and an error and a hint message.
You may omit defining a hint message in which case the error message will be passed as hintMessage
to the renderField
function.
Validations are passed to the ReformContext
component. This is where you assign a name to a validation. Have a look at this example to know how it works:
import React, {Component} from 'react'
import {render} from 'react-dom'
import {ReformContext, createTheme} from 'react-reform'
const defaultTheme = createTheme(...)
const validations = {
validUserName: {
isValid: val => /#\W+(-\W+)*/.test(val),
errorMessage: () => 'is not a valid username',
hintMessage: () => 'may contain letters, digits, underscores and dashes'
},
maxLength: {
isValid: (val, {arg}) => (val || '').toString().length <= arg,
errorMessage: (val, {arg}) => {
const currLength = (val || '').toString().length
return `maximal length: ${currLength}/${arg}`
},
hintMessage: (val, {arg}) => 'may contain letters at most ${arg} chars'
}
}
class App extends Component {
render() {
return (
<ReformContext themes={{default: defaultTheme}} validations={validations}>
<div>
...Your App Code...
</div>
</ReformContext>
)
}
}
render(<App/>, document.getElementById('root'))
The two validations validUserName
and maxLength
may be used within inputs when prefixing either is
or has
:
<Form onSubmit={this.handleSubmit}>
<Text name="name" isValidUserName/>
<Textarea name="about" hasMaxLength={140}/>
</Form>
(val, data, revalidateFn) => (true|false|string)
This function determines whether a given input is valid or not. You may also return something else than true
or false
in case you have more states like e.g. "pending"
. But be aware that submitting a form will only suceed if all inputs' validations return true
.
val
Contains the current value of the input.
data.arg
You may add options to a validation like <Text name="content" hasMaxLength={140}/>
or even <Textarea name="username" isUnique={{attribute: 'name', label: 'this better be a unique name'}}/>
. You can access the passed prop value via this field.
data.getValue(fieldName)
In case you want to access other field's values use this function. Imagine an input like <Text name="passwordRepeat" hasSameValueAs="password"/>
, a useful implementation would be:
{
isValid: (val, {arg, getValue}) => val === getValue(arg),
...
}
revalidateFn
When dealing with asynchronous validatoins, you need to tell React Reform to revalidate the input once a result gets back to you. Use this function to do exactly this. See the section below for a full example.
(val, data) => (string|React element)
Use this to define two types of messages for your validation. The hintMessage
is optional and the errorMessage
's output will be used in the renderField
function
val
Contains the current value of the input.
data.arg
Same as isValid
's data.arg
described above.
data.name
Contains the name of the field.
It's also possible to define asynchronous validations. The API is rather similar. But rather than defining a validation description like above we're using a function returning a validation description:
const validations = {
unique: () => {
const cachedResults = {}
return {
isValid: (val, data, askAgain) => {
if (!val) return true
if (cachedResults[val] === undefined) {
cachedResults[val] = 'pending'
setTimeout(() => {
cachedResults[val] = Math.random() > 0.5
askAgain()
}, 1000)
}
return cachedResults[val]
},
errorMessage: (val, {arg}) => `has to be unique. But '${val}' isn't`
}
}
}
This function gets invoked once the input is mounted. This means that the cachedResults
variable is unique for each input using this validation.
As you can see we're doing any real request but simulate this via setTimeout
. We fill the cache with a value and return this value on any subsequent validation request. Once we receive the proper value, we're calling the third argument of the isValid
function, indicating that we'd like to be asked again, whether the input is valid.