react-native-sk-validatable-form v1.0.1
react-native-sk-validatable-form
##Why it comes
Inspired by react-native-gifted-form and formsy-react, I appreciate these project, but I want more:
- Validate form fields in react-native.
- Easy to add validation rules and messages, and use them with simple syntax.
- Field's state(value) should be maintained by itself, not by form, but form can get fields' value, not store them.
- Validation rule should be declarative, it should follow component's declaration, e.g.
<TextInput validations='isRequired,isLength:[1,50]'/> - Each rule binds one error message, when you call a rule everywhere, you don't need write the message everywhere.
- Field component should be easy to extend, not just traditional input components(e.g. TextInput, Swith), but any other input components.
- Form scrolls to the focused input component automatically.
So I come up with this project.
##What is it
react-native-sk-validatable-form is a component that wraps your form fields, it’s easy to get their value, validate their value.
There are some concepts you need to know
- Form: Component that represents a form, wraps ScrollView, contains input components, validates/gets their values
- Widget: Component that represents a field, wraps input components(e.g. TextInput/Switch) to accept field's value, validates/get its value, keeps validation error. You can create a Widget class by 2 ways: 1 inherits
WidgetMixin2 useWidgetClassFactory. You can set validation rules through 'validations' property (e.g.validations='isRequired,isLength:[1,50]') - Validation: Class that parse validation rules and checks the rules. You can add rule validator through Validation.addValidator(rule, func)
- Message: Helper that contains every rule's error message template, and translates it into real message. You can add a message templdate for a rule through Message.addMessage(rule, messageTemplate)
##How to use it
Example
npm install react-native-sk-validatable-form@latest --saveWrite this in index.ios.js / index.android.js
'use strict';
import React, {
AppRegistry,
Alert,
} from 'react-native';
var {SKNavigator} = require('react-native-sk-navigator');
var { Form, Widget, WidgetMixin, WidgetClassFactory, Validation, Message } = require('react-native-sk-validatable-form');
// 如果你想显示中文的错误消息
// Message.setLanguage('cn');
var Home = React.createClass({
submit(){
var title, msg;
if(this.refs.form.validate()){ // validate form (validate all fields' value in form)
title = 'Success';
msg = 'validate success';
}else{
title = 'Fail';
msg = this.refs.form.getErrorMessages().join('\n'); // get all fields' validation error message
}
Alert.alert(
title,
msg,
[
{text:'ok'},
]
);
},
render() {
return (
<Form
ref='form'
navigator={this.props.navigator}
keyboardShouldPersistTaps={true}
scrollEventThrottle={200}
style={[styles.container, this.props.style]}>
{/* title 标题 */}
<Widget.TextInputInline
name='title' // field name
title='title' // field title
validations='isRequired,isLength:[1,50]' // field's validation rules
validateOnBlur={true} // validate when input component blurs / onBlur() happens
maxLength={50}
style={[styles.textInput, styles.titleInput]}
placeholderTextColor='#B9B9B9'
placeholder='Please input title(limit 50 character)'
/>
{/* married 已婚 */}
<Widget.SwitchInline
name='married'
title='married'
defaultValue={false}
onTintColor='#F59E21'
validations='isRequired'
/>
{/* sex 性别 */}
<Widget.SexLinkInline
name='sex1'
title='sex1'
validations='isRequired'
placeholder='Please select sex'
/>
{/* sex 性别 */}
<Widget.PickerIOSLinkInline
name='sex2'
title='sex2'
validations='isRequired'
placeholder='Please select sex'
items={{'female': 'Female/Woman', 'male': 'Male/Man'}}
/>
{/* sex 性别 */}
<Widget.PickerLinkInline
name='sex3'
title='sex3'
validations='isRequired'
placeholder='Please select sex'
items={{'female': 'Female/Woman', 'male': 'Male/Man'}}
/>
{/* date 日期 */}
<Widget.DateIOSLinkInline
name='date'
title='date'
validations='isRequired'
placeholder='please select date'
/>
{/* place 地点 */}
<Widget.MapLinkInline
name='place'
title='place'
validations='isRequired'
placeholder='please select place'
/>
{/* content 内容 */}
<Widget.TextInput
name='content'
title='content'
validations='isRequired,isLength:[1,200]'
validateOnBlur={true}
maxLength={200}
style={[styles.textInput, styles.contentInput]}
placeholderTextColor='#B9B9B9'
placeholder='Please input content'
onFocus={() => this.refs.form.scrollTo({y: 60})}
multiline={true}
/>
</Form>
);
}
});
var SKFormExample = React.createClass({
render() {
return (
<SKNavigator
initialRoute={{ // 初始路由
title: 'Home',
component: Home,
passProps: {
ref: (ref) => this.home = ref,
},
rightButtonTitle: 'submit',
onRightButtonPress: () => this.home.submit(),
}}/>
)
}
})
var styles = {
container: {
flex: 1,
backgroundColor: '#FFF',
},
textInput:{
fontSize: 15,
},
titleInput: {
flex: 1,
color: 'black',
},
contentInput: {
marginLeft: 10,
height: 160,
color: '#5E5D5D',
},
};
AppRegistry.registerComponent('SKFormExample', () => SKFormExample);
##Form Component
Form wraps ScrollView, contains widgets, validates/gets their values, and scrolls to the focused input component automatically.
Form's properties
Form's methods
| Method | Description | Params |
|---|---|---|
registerInput(widget) | Remember a input widget. | None |
unregisterInput(widget) | Forget a input widget. | None |
scrollTo(...) | Delegate ScrollView's method scrollTo(). | None |
scrollToFocusedInput(input) | Scroll to the focuse input widget. | None |
getTitles() | Get all fields' title. | None |
getValues() | Get all fields' value. | None |
validate() | Validate all fields' value. | None |
getErrorMessages() | Get all fields' validation error message. | None |
##Widget Component(Inherits WidgetMixin)
Widget's properties
Any property of input component(e.g. TextInput/Switch) which widget wraps(Widget will pass these properties to input component).
And the following:
| Prop | Description | Default |
|---|---|---|
name | Field name. | None |
title | Field title. | None |
defaultValue | Field's default value. | None |
validations | Field's validation rules. | None |
validateOnBlur | Validate when input component blurs / onBlur() happens. | false |
Widget's methods
| Method | Description | Params |
|---|---|---|
setValue(value) | Set current field's value. | None |
getValue() | Get current field's value. | None |
validate() | Validate current field' value. | None |
getErrorMessage() | Get current field' validation error message. | None |
How to define a widget
1 inherits WidgetMixin
var TextInputWidget = React.createClass({
mixins: [WidgetMixin],
render(){
return (
<TextInput
{...this.props}
onChangeText={this.setValue}
value={this.state.value} />
)
}
})2 use WidgetClassFactory
WidgetClassFactory is a helper to define a widget, with the same inplements as above(1 inherits WidgetMixin).
create() method needs 3 parameters:
1 input component
2 value change callback (e.g. TextInput.onChangeText / Switch.onValueChange)
3 value property (e.g TextInput.value / Switch.value)
var TextInputWidget = WidgetClassFactory.create(TextInput, 'onChangeText', 'value');Widegt's uses
<TextInputWidget
name='title' // field name
title='title' // field title
validations='isRequired,isLength:[1,50]' // field's validation rules
validateOnBlur={true} // validate when input component blurs / onBlur() happens
/>Validation rules string
validations='isRequired,isLength:[1,50],equalsPassword:#password'validations contains validation rules, which is defined in validator or you can define it yourself by Validation.addValidator(rule, func).
Multiple rules are split by ,.
One rule contains name and parameter which are split by :.
Parameter can be a json(e.g. [1,50]) or a string(e.g. abc123) or a field(e.g. #xxx, it will pass 'xxx' field's value when check the rule)
Validation Class
Validation is a class that contains validation rules, and will check the rules.
Validation's methods
| Method | Description | Params |
|---|---|---|
static addValidator(rule, func) | Add a rule validator, which is used by Validation rules string | None |
static parse(validations) | Parse validation rules string (into a Validation object). | None |
check(value, values) | check the rules, called by WidgetMixin.validate() | None |
Add a rule validator
Validation.addValidator('equalsPassword', (value, password) => {
return value == password;
})Each rule has a validator function, which check the rule and return bool result.
Message helper
Message is a helper to offer error message for a rule.
Message's methods
| Method | Description | Params |
|---|---|---|
setLanguage(language, messages = null) | Toggle language, only support cn(chinese) and en(english), you can add your implements by parameter messages. | None |
addMessage(rule, messageTemplate) | add a message template for a rule. | None |
Toggle message language
// If you want to show chinese error message, 如果你想显示中文的错误消息
Message.setLanguage('cn');Add a message templdate for a rule
Message.addMessage('isEmail', '{TITLE} must be an email');
Message.addMessage('equalsPassword', '{TITLE} must be an {password}');In Message.addMessage(rule, messageTemplate), messageTemplate is a string template which contains parameter and will be translated when showing a error message.
About messageTemplate parameters, {TITLE} represents current field's title, {xxx} represents 'xxx' field's title.