Skip to content

Instantly share code, notes, and snippets.

@iegik
Last active December 5, 2017 09:53
Show Gist options
  • Save iegik/28c177a5603ba293e36b7da5875618ad to your computer and use it in GitHub Desktop.
Save iegik/28c177a5603ba293e36b7da5875618ad to your computer and use it in GitHub Desktop.
Form validation
export const sendMessage = () => new Promise((res, rej) => {
setTimeout(res, 1000, true)
});
import React from 'react';
import {reduce} from 'lodash';
import {createValidation, isRequired, isPhone, isEmail} from '../../../utils/validation';
export default (props = {}) => {
let {
values,
errors,
onChangeField,
onSend,
isSubmitted,
isFresh,
} = props;
let hasErrors = !!reduce(errors, (has, errors) => {
if (errors && errors.length) {
has++
}
return has;
}, 0);
return (
<form onSubmit={onSend}>
<div>
<label htmlFor="bid-id">ID</label>
<input type="text" autoComplete="off" id="bid-id" value={values.id}
onChange={e => onChangeField('id', e.target.value, createValidation([]))}
onBlur={e => onChangeField('id', e.target.value, createValidation([[isRequired,'Is required']]))}
/>
{ errors.id && errors.id.length ? (
<div>{errors.id[0]}</div>
) : (
<div>{'Some description'}</div>
) }
</div>
<div>
<label htmlFor="bid-phone">Телефон</label>
<input type="text" id="bid-phone" value={values.phone}
onChange={e => onChangeField('phone', e.target.value, createValidation([[isPhone, 'Should be a valid mobile phone']]))}
onBlur={e => onChangeField('phone', e.target.value, createValidation([[isRequired,'Is required']]))}
/>
{ errors.phone && errors.phone.length ? (
<div>{errors.phone[0]}</div>
) : (
<div>{'Some description'}</div>
) }
</div>
<div>
<label htmlFor="bid-email">email</label>
<input type="text" id="bid-email" value={values.email}
onChange={e => onChangeField('email', e.target.value, createValidation([[isEmail, 'Should be a valid email']]))}
onBlur={e => onChangeField('email', e.target.value, createValidation([[isRequired,'Is required']]))}
/>
{ errors.email && errors.email.length ? (
<div>{errors.email[0]}</div>
) : (
<div>{'Some description'}</div>
) }
</div>
<div>
<input type="submit" disabled={isSubmitted || hasErrors || isFresh} />
</div>
</form>
)
}
import React, { Component } from 'react';
import { reduce } from 'lodash';
export default View => class extends Component {
state = {
values: {},
errors: {},
isSubmitted: false,
isFresh: true,
onChangeField: (field, value, validation) => {
let { values, errors } = this.state;
this.setState({
values: { ...values, [field]: value },
errors: { ...errors, [field]: validation(value) },
isFresh: false,
});
},
onSend: async (e) => {
let { values, errors, isSubmitted } = this.state;
e.preventDefault();
if (!reduce(errors, (p, e) => p + e.length, 0) || !isSubmitted) {
this.setState({ isSubmitted: true });
try {
this.setState({ status: await this.props.onSubmit(values) })
} catch (e) {
this.setState({ errors: { ...errors, status: e.message } })
}
}
},
};
render(){
return <View {...{...this.props,...this.state}} />;
}
}
import Example from './example';
import Form from './Form';
import {sendMessage} from './api'; // Promise
@Form
class ExampleForm extends Component {
render() {
// {errors, values} = this.state
return Example({...this.props, ...this.state});
}
}
ExampleForm.defaultProps = { onSubmit: sendMessage }
export default ExampleForm;
import {reduce} from 'lodash';
import {isEmpty, isMobilePhone} from 'validator';
export * from 'validator';
export const isRequired = value => !isEmpty(value);
export const isPhone = value => isMobilePhone(value, 'ru-RU');
export const createValidation = (checks = []) => {
return value => reduce(checks, (errors, check) => {
if (!check[0](value)) errors.push(check[1]);
return errors;
}, [])
};
import {isEmail, isRequired, isPhone, createValidation} from './validation';
describe('validators', () => {
it('should validate isRequired', () => {
expect(isRequired('')).toBeFalsy();
expect(isRequired('1')).toBeTruthy();
});
it('should validate isEmail', () => {
expect(isEmail('1')).toBeFalsy();
expect(isEmail('[email protected]')).toBeTruthy();
});
it('should validate isMobilePhone', () => {
expect(isPhone('1')).toBeFalsy();
expect(isPhone('+79218888888')).toBeTruthy();
});
});
describe('validate', () => {
let validate = createValidation([[isRequired,3], [isEmail, 5]]);
it('should return all mached messages', () => {
expect(validate('')).toEqual([3,5])
});
it('should return one mached message', () => {
expect(validate('1')).toEqual([5])
});
it('should not return any message', () => {
expect(validate('[email protected]')).toEqual([])
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment