From 891341532b95953d028edf7250c1798c973903da Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Fri, 25 Sep 2015 12:53:29 -0700 Subject: [PATCH] refactor form to do validation right in component --- common/app/routes/Jobs/components/NewJob.jsx | 135 ++++++++----------- common/app/routes/Jobs/flux/Actions.js | 47 +------ common/app/routes/Jobs/utils.js | 2 +- 3 files changed, 58 insertions(+), 126 deletions(-) diff --git a/common/app/routes/Jobs/components/NewJob.jsx b/common/app/routes/Jobs/components/NewJob.jsx index b160671c4b5..12f9b425a01 100644 --- a/common/app/routes/Jobs/components/NewJob.jsx +++ b/common/app/routes/Jobs/components/NewJob.jsx @@ -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({

Make it stand out

{ - this.handleChange( - 'highlight', - () => { return true; }, - e - ); - }} - type='checkbox' - value={ highlight.value } /> + onChange={ + ({ target: { checked } }) => handleForm({ + highlight: !!checked + }) + } + type='checkbox' />
{} }) { - 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 }; } }) diff --git a/common/app/routes/Jobs/utils.js b/common/app/routes/Jobs/utils.js index 3a60c373a8b..aeb0396c125 100644 --- a/common/app/routes/Jobs/utils.js +++ b/common/app/routes/Jobs/utils.js @@ -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]); }