Skip to content

Commit

Permalink
add validate to simpleForm and TextInput
Browse files Browse the repository at this point in the history
  • Loading branch information
infinite-yy committed Aug 21, 2017
1 parent 31cbe76 commit 38142fd
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 13 deletions.
33 changes: 24 additions & 9 deletions src/widgets/form/SimpleForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,52 @@ import Toolbar from './Toolbar';
import MobxReactForm from 'mobx-react-form';
import { SaveButton } from '../button';

import {validateForm} from '../validate'

class DefaultForm extends MobxReactForm { }


@observer
export default class SimpleForm extends React.Component {
@validateForm
class SimpleForm extends React.Component {
constructor(){
super();
this.inputs = [];
}
render() {
let { record, children, onSubmit, invalid, form, fields, showToolbar, plugins } = this.props
const submitHandler = (e) => {
e.preventDefault();
if (onSubmit) {
onSubmit(this.record)
onSubmit(record)
}
e.preventDefault();
}
if (form == null) {
form = new DefaultForm(fields, plugins)
}
const createChangeHandler = (element) => {
return (e) => {
//this.handleFieldChange(e, element.props.source, e.target.value)
if (element.props.onChange) {
element.props.onChange(e, element.props.source, e.target.value)
}

// //this.handleFieldChange(e, element.props.source, e.target.value)
// if (element.props.onChange) {
// element.props.onChange(e, element.props.source, e.target.value)
// }
}
}
return <form onSubmit={submitHandler}>
<div style={{ padding: '0 1em 1em 1em' }}>
{React.Children.map(children, input => (
<div key={input.props.source} style={input.props.style}>
{React.cloneElement(input, { record: record, source: input.props.source, onChange: createChangeHandler(input) })}
{React.cloneElement(input, { record: record, source: input.props.source, onChange: createChangeHandler(input), ref: component => {this.inputs.push(component)}})}
</div>
))}
</div>
{showToolbar && <Toolbar invalid={invalid} />}
</form>
}
}
}

export default SimpleForm;



17 changes: 13 additions & 4 deletions src/widgets/input/TextInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { observer } from 'mobx-react'
import TextField from 'material-ui/TextField';
import { fetchValue, writeValue } from '../utils'

import {validateInput} from '../validate'

/**
* An Input component for a string
*
Expand All @@ -21,23 +23,30 @@ import { fetchValue, writeValue } from '../utils'
*/
@observer
class TextInput extends Component {
@validateInput
handleChange = (event) => {
this.props.writeValue(this, event.target.value)
if (this.props.onChange) {
this.props.onChange(event, this.props.source, event.target.value)
}


}

@observable _errorText;
@observable _value = ''
render() {
const { fetchValue, label, style, type, disabled} = this.props
const { fetchValue, label, style, type, disabled } = this.props
return <TextField
label={label}
style={style}
type={type}
disabled={disabled}
value={fetchValue(this)}
onChange={this.handleChange}
value={this._value}
onChange={this.handleChange.bind(this)}
floatingLabelText={<span>{label}</span>}

errorText={this._errorText || ''}
/>
}
}
Expand All @@ -53,7 +62,7 @@ TextInput.propTypes = {
fetchValue: PropTypes.func,
writeValue: PropTypes.func,
type: PropTypes.string,
convert: PropTypes.oneOfType([PropTypes.func,PropTypes.object])
convert: PropTypes.oneOfType([PropTypes.func, PropTypes.object])
};

TextInput.defaultProps = {
Expand Down
142 changes: 142 additions & 0 deletions src/widgets/validate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import React from 'react';
import { getValues } from './utils'

export function validateInput(target, key, descriptor) {
const method = descriptor.initializer;
descriptor.initializer = function () {
return function (event) {
this.props.validators.map((validator, index) => {
check.apply(this, [validator, this.props.errorMessages[index], event.target.value]);
});
this._value = event.target.value;
method.apply(this)(event);
}
};
return descriptor;
}
export function validateForm(Form) {

return class extends React.Component {
onSubmit(data) {
if (this.wci) {
let all_clear = true;
this.wci.map((child) => {
if (child.props.validators) {
for (var i = 0, l = child.props.validators.length; i < l; i++) {
if (!check.apply(child, [child.props.validators[i], child.props.errorMessages[i], getValues(child.props.record, child.props.source)[0]])) {
all_clear = false;
break;
}
}
}
});
if (all_clear) {
console.log('all clear');
this.props.onSubmit(data);
}
}
}
proc(wrappedComponentInstance) {
if(wrappedComponentInstance){
this.wci = wrappedComponentInstance.inputs;
}
}
render() {
const props = Object.assign({}, this.props, { ref: this.proc.bind(this) })
return <Form {...props} onSubmit={this.onSubmit.bind(this)} />
}
}
}

function check(validator, errorMsg, data) {
if (!getValidator(validator)(data)) {
this._errorText = errorMsg;
this.props.writeValue(this, 'Error');
return false;
} else {
this._errorText = '';
return true;
}
}

function getValidator(validator) {
switch (validator) {
case 'required':
return validations.required
break;
case 'email':
return validations.isEmail
break;
case 'phone':
return validations.isNumber
break;
default:
return function () { return true };
}
}

// ValidationRules
// copy from <react-material-ui-form-validator | https://github.com/NewOldMax/react-material-ui-form-validator>
// -----------------------------------------------------------------------------------------------------------------
var isExisty = function isExisty(value) {
return value !== null && value !== undefined;
};

var _isEmpty = function _isEmpty(value) {
return value === '' || value === undefined || value == null;
};

var isEmptyTrimed = function isEmptyTrimed(value) {
if (typeof value === 'string') {
return value.trim() === '';
}
return true;
};

var validations = {
matchRegexp: function matchRegexp(value, regexp) {
var validationRegexp = regexp instanceof RegExp ? regexp : new RegExp(regexp);
return !isExisty(value) || _isEmpty(value) || validationRegexp.test(value);
},

// eslint-disable-next-line
isEmail: function isEmail(value) {
return validations.matchRegexp(value, /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i);
},

isEmpty: function isEmpty(value) {
return _isEmpty(value);
},

required: function required(value) {
return !_isEmpty(value);
},

trim: function trim(value) {
return !isEmptyTrimed(value);
},

isNumber: function isNumber(value) {
return validations.matchRegexp(value, /^-?[0-9]\d*(\d+)?$/i);
},

isFloat: function isFloat(value) {
return validations.matchRegexp(value, /^(?:[1-9]\d*|0)?(?:\.\d+)?$/i);
},

isPositive: function isPositive(value) {
if (isExisty(value)) {
return (validations.isNumber(value) || validations.isFloat(value)) && value >= 0;
}
return true;
},

maxNumber: function maxNumber(value, max) {
return !isExisty(value) || _isEmpty(value) || parseInt(value, 10) <= parseInt(max, 10);
},

minNumber: function minNumber(value, min) {
return !isExisty(value) || _isEmpty(value) || parseInt(value, 10) >= parseInt(min, 10);
}
};
// -----------------------------------------------------------------------------------------------------------------

0 comments on commit 38142fd

Please sign in to comment.