I am writing validation library for redux-form using redux-localize-redux.
The followings are snippets from my project.
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Field, reduxForm } from 'redux-form';
import compose from 'recompose/compose';
import { getTranslate, getActiveLanguage, addTranslation } from 'react-localize-redux';
import {
Checkbox,
RadioButtonGroup,
SelectField,
TextField,
Toggle,
DatePicker
} from 'redux-form-material-ui';
import IconButton from 'material-ui/IconButton';
import Input, { InputLabel, InputAdornment } from 'material-ui/Input';
import Visibility from 'material-ui-icons/Visibility';
import VisibilityOff from 'material-ui-icons/VisibilityOff';
import { withStyles } from 'material-ui/styles'
import { FormControl, FormHelperText } from 'material-ui/Form';
import MailOutline from 'material-ui-icons/MailOutline';
import NinesqTextField from './NinesqTextField';
import NinesqEmailField from './NinesqEmailField';
import NinesqPasswordField from './NinesqPasswordField';
import NineSqValidatorObj from './NineSqValidatorObj';
const styles = theme => ({
flash_on: {
display: 'block',
},
flash_off: {
display: 'none',
},
fieldOutline: {
fontWeight: 300,
borderRadius: 2,
border: '1px solid red',
boxSizing: 'border-box',
},
});
const messages = {
"LocalLoginForm": {
"email_placeholder": [
"이메일 주소",
"Email Address",
"JP-Email Address",
"ZH-Email Address",
"FR-Email Address",
"ES-Email Address"
],
"email_label": [
"이메일",
"Email",
"JP-Email",
"ZH-Email",
"FR-Email",
"ES-Email"
],
"password_label": [
"패스워드",
"Password",
"JP-Password",
"ZH-Password",
"FR-Password",
"ES-Password"
],
"password_placeholder": [
"패스워드",
"Password",
"JP-Password",
"ZH-Password",
"FR-Password",
"ES-Password"
],
"submit_label": [
"로그인",
"Log in",
"JP-Log in",
"ZH-Log in",
"FR-Log in",
"ES-Log in"
]
}
};
export class LocalLoginForm extends Component {
static propTypes = {
classes: PropTypes.object.isRequired,
}
state = {
showPassword: true,
nsvalidator: new NineSqValidatorObj(this.props.dispatch, this.props.translate)
}
componentWillMount = () => {
console.log("componentWillMount");
this.props.dispatch(addTranslation(messages));
}
render() {
const { handleSubmit, pristine, reset, submitting, translate, auth, classes } = this.props;
return (
<form onSubmit={handleSubmit}>
<div className={classes.fieldOutline}>
<Field name="myField"
fullWidth
validate={[this.state.nsvalidator.required]}
component={NinesqEmailField}
label={translate('LocalLoginForm.email_placeholder')}
placeholder={translate('LocalLoginForm.email_placeholder')}
/>
</div>
<div className={classes.fieldOutline}>
<Field name="mypassword"
fullWidth
validate={[this.state.nsvalidator.required]}
component={NinesqPasswordField}
placeholder={translate('LocalLoginForm.password_placeholder')}
label={translate('LocalLoginForm.password_placeholder')}
/>
</div>
<div className={auth.error ? classes.flash_on: classes.flash_off}>{`error: ${auth.error}`}</div>
<div><button type="submit">{translate('LocalLoginForm.submit_label')}</button></div>
</form>
)
}
}
const mapStateToProps = (state, props) => ({
auth: state.auth.auth,
translate: getTranslate(state.locale),
currentLanguage: getActiveLanguage(state.locale).code
});
const mapDispatchToProps = {
}
export default compose(reduxForm({form: 'localLogin'}), connect(mapStateToProps, mapDispatchToProps), withStyles(styles))(LocalLoginForm);
import { getTranslate, getActiveLanguage, addTranslation } from 'react-localize-redux';
const messages = {
"validate": {
"required": [
"필수항목",
"Required",
"JP-Required",
"ZH-Required",
"FR-Required",
"ES-Required"
],
}
};
class NineSqValidatorObj {
constructor(dispatch, translate) {
dispatch(addTranslation(messages));
this.translate = translate;
this.required = this.required.bind(this);
}
required(value){
return (value ? undefined : this.translate('validate.required'));
}
maxLength(max) {
return value => value && value.length > max ? `Must be ${max} characters or less` : undefined;
}
maxLengthEmail = this.maxLength(15);
minLength(min) {
return value =>
value && value.length < min ? `Must be ${min} characters or more` : undefined;
}
minLength2 = this.minLength(2);
number(value) {
return value && isNaN(Number(value)) ? 'Must be a number' : undefined;
}
minValue(min) {
return value => value && value < min ? `Must be at least ${min}` : undefined;
}
minValue18 = this.minValue(18);
email(value) {
return value && !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(value)
? 'Invalid email address'
: undefined;
}
alphaNumeric(value) {
return value && /[^a-zA-Z0-9 ]/i.test(value)
? 'Only alphanumeric characters'
: undefined;
}
phoneNumber(value) {
return value && !/^(0|[1-9][0-9]{9})$/i.test(value)
? 'Invalid phone number, must be 10 digits'
: undefined;
}
}
export default NineSqValidatorObj;
I could try to implement it as HOC, however I thought it's wired to have render() in validator functions. So simply use it as a class. The current symptom is it won't find validate.required key.