@Form
Last active
December 5, 2017 09:53
-
-
Save iegik/28c177a5603ba293e36b7da5875618ad to your computer and use it in GitHub Desktop.
Form validation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export const sendMessage = () => new Promise((res, rej) => { | |
setTimeout(res, 1000, true) | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> | |
) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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}} />; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
}, []) | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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