refactor form to do validation right in component

pull/3525/head
Berkeley Martinez 2015-09-25 12:53:29 -07:00
parent c63a983fb9
commit 891341532b
3 changed files with 58 additions and 126 deletions

View File

@ -37,22 +37,31 @@ const checkValidity = [
'highlight'
];
function formatValue(value, validator, type = 'string') {
const formated = getDefaults(type);
if (validator && type === 'string') {
formated.valid = validator(value);
}
if (value) {
formated.value = value;
formated.bsStyle = formated.valid ? 'success' : 'error';
}
return formated;
}
function isValidURL(data) {
return isURL(data, { 'require_protocol': true });
}
function isValidPhone(data) {
return isMobilePhone(data, 'en-US');
}
export default contain({
actions: 'jobActions',
store: 'jobsStore',
map({ form = {} }) {
const {
position = getDefaults('string'),
locale = getDefaults('string'),
description = getDefaults('string'),
email = getDefaults('string'),
phone = getDefaults('string'),
url = getDefaults('string'),
logo = getDefaults('string'),
name = getDefaults('string'),
highlight = getDefaults('bool')
} = form;
return {
position,
locale,
description,
@ -62,6 +71,17 @@ export default contain({
logo,
name,
highlight
} = form;
return {
position: formatValue(position, isAscii),
locale: formatValue(locale, isAscii),
description: formatValue(description, isAscii),
email: formatValue(email, isEmail),
phone: formatValue(phone, isValidPhone),
url: formatValue(url, isValidURL),
logo: formatValue(logo, isValidURL),
name: formatValue(name, isAscii),
highlight: formatValue(highlight, null, 'bool')
};
},
subscribeOnWillMount() {
@ -86,11 +106,12 @@ export default contain({
handleSubmit(e) {
e.preventDefault();
const props = this.props;
let valid = true;
checkValidity.forEach((prop) => {
// if value exist, check if it is valid
if (this.props[prop].value) {
valid = valid && !!this.props[prop].valid;
if (props[prop].value && props[prop].type !== 'boolean') {
valid = valid && !!props[prop].valid;
}
});
@ -141,9 +162,9 @@ export default contain({
jobActions.getSavedForm();
},
handleChange(name, validator, { target: { value } }) {
handleChange(name, { target: { value } }) {
const { jobActions: { handleForm } } = this.props;
handleForm({ name, value, validator });
handleForm({ [name]: value });
},
render() {
@ -156,8 +177,10 @@ export default contain({
url,
logo,
name,
highlight
highlight,
jobActions: { handleForm }
} = this.props;
const { handleChange } = this;
const labelClass = 'col-sm-offset-1 col-sm-2';
const inputClass = 'col-sm-6';
@ -178,13 +201,7 @@ export default contain({
bsStyle={ position.bsStyle }
label='Position'
labelClassName={ labelClass }
onChange={ (e) => {
this.handleChange(
'position',
isAscii,
e
);
}}
onChange={ (e) => handleChange('position', e) }
placeholder='Position'
type='text'
value={ position.value }
@ -193,13 +210,7 @@ export default contain({
bsStyle={ locale.bsStyle }
label='Location'
labelClassName={ labelClass }
onChange={ (e) => {
this.handleChange(
'locale',
isAscii,
e,
);
}}
onChange={ (e) => handleChange('locale', e) }
placeholder='Location'
type='text'
value={ locale.value }
@ -208,13 +219,7 @@ export default contain({
bsStyle={ description.bsStyle }
label='Description'
labelClassName={ labelClass }
onChange={ (e) => {
this.handleChange(
'description',
isAscii,
e
);
}}
onChange={ (e) => handleChange('description', e) }
placeholder='Description'
rows='10'
type='textarea'
@ -228,13 +233,7 @@ export default contain({
bsStyle={ name.bsStyle }
label='Company Name'
labelClassName={ labelClass }
onChange={ (e) => {
this.handleChange(
'name',
isAscii,
e,
);
}}
onChange={ (e) => handleChange('name', e) }
placeholder='Foo, INC'
type='text'
value={ name.value }
@ -243,13 +242,7 @@ export default contain({
bsStyle={ email.bsStyle }
label='Email'
labelClassName={ labelClass }
onChange={ (e) => {
this.handleChange(
'email',
isEmail,
e
);
}}
onChange={ (e) => handleChange('email', e) }
placeholder='Email'
type='email'
value={ email.value }
@ -258,13 +251,7 @@ export default contain({
bsStyle={ phone.bsStyle }
label='Phone'
labelClassName={ labelClass }
onChange={ (e) => {
this.handleChange(
'phone',
(data) => isMobilePhone(data, 'en-US'),
e
);
}}
onChange={ (e) => handleChange('phone', e) }
placeholder='555-123-1234'
type='tel'
value={ phone.value }
@ -273,13 +260,7 @@ export default contain({
bsStyle={ url.bsStyle }
label='URL'
labelClassName={ labelClass }
onChange={ (e) => {
this.handleChange(
'url',
(data) => isURL(data, { 'require_protocol': true }),
e
);
}}
onChange={ (e) => handleChange('url', e) }
placeholder='http://freecatphotoapp.com'
type='url'
value={ url.value }
@ -288,13 +269,7 @@ export default contain({
bsStyle={ logo.bsStyle }
label='Logo'
labelClassName={ labelClass }
onChange={ (e) => {
this.handleChange(
'logo',
(data) => isURL(data, { 'require_protocol': true }),
e
);
}}
onChange={ (e) => handleChange('logo', e) }
placeholder='http://freecatphotoapp.com/logo.png'
type='url'
value={ logo.value }
@ -304,17 +279,15 @@ export default contain({
<h2>Make it stand out</h2>
</div>
<Input
checked={ highlight.value }
label='Highlight your ad'
labelClassName={ 'col-sm-offset-1 col-sm-6'}
onChange={ (e) => {
this.handleChange(
'highlight',
() => { return true; },
e
);
}}
type='checkbox'
value={ highlight.value } />
onChange={
({ target: { checked } }) => handleForm({
highlight: !!checked
})
}
type='checkbox' />
<div className='spacer' />
<Row>
<Col

View File

@ -1,6 +1,5 @@
import { Actions } from 'thundercats';
import store from 'store';
import { getDefaults } from '../utils';
import debugFactory from 'debug';
const debug = debugFactory('freecc:jobs:actions');
@ -41,32 +40,7 @@ export default Actions({
closeModal() {
return { showModal: false };
},
handleForm({ name, value, validator = () => {} }) {
if (!name) {
// operation noop
return { replace: null };
}
if (!validator(value)) {
return {
transform(oldState) {
const { form } = oldState;
const newState = assign({}, oldState);
newState.form = assign(
{},
form,
{
[name]: {
value,
valid: false,
pristine: false,
bsStyle: value ? 'error' : null
}
}
);
return newState;
}
};
}
handleForm(value) {
return {
transform(oldState) {
const { form } = oldState;
@ -74,14 +48,7 @@ export default Actions({
newState.form = assign(
{},
form,
{
[name]: {
value,
valid: true,
pristine: false,
bsStyle: value ? 'success' : null
}
}
value
);
return newState;
}
@ -89,15 +56,7 @@ export default Actions({
},
saveForm: null,
getSavedForm: null,
setForm(job) {
const form = Object.keys(job).reduce((accu, prop) => {
console.log('form', accu);
return Object.assign(
accu,
{ [prop]: getDefaults(typeof prop, job[prop]) }
);
}, {});
setForm(form) {
return { form };
}
})

View File

@ -18,5 +18,5 @@ export function getDefaults(type, value) {
if (value) {
return Object.assign({}, defaults[type], { value });
}
return defaults[type];
return Object.assign({}, defaults[type]);
}