Rewrite form in ES6

old
Javi Velasco 2015-09-20 23:27:28 +02:00
parent 1747330fef
commit d0ab1ddbf0
3 changed files with 160 additions and 106 deletions

View File

@ -1,105 +0,0 @@
localCSS = require './style'
Autocomplete = require '../autocomplete'
Dropdown = require '../dropdown'
Button = require '../button'
Input = require '../input'
Switch = require '../switch'
module.exports = React.createClass
# -- States & Properties
propTypes:
attributes : React.PropTypes.array
className : React.PropTypes.string
onChange : React.PropTypes.func
onError : React.PropTypes.func
onSubmit : React.PropTypes.func
onValid : React.PropTypes.func
storage : React.PropTypes.string
getDefaultProps: ->
attributes : []
className : ''
getInitialState: ->
attributes : @storage @props
# -- Lifecycle
componentWillReceiveProps: (next_props) ->
if next_props.attributes
attributes = @storage next_props
@setState attributes: attributes
@setValue (item for item in attributes)
# -- Events
onSubmit: (event) ->
event.preventDefault()
@props.onSubmit? event, @
onChange: (event) ->
is_valid = true
value = @getValue()
for attr in @state.attributes when attr.required and value[attr.ref]?.trim() is ""
is_valid = false
@refs[attr.ref].setError? 'Required field'
break
@props.onChange? event, @
@storage @props, value if @props.storage
if is_valid
@refs.submit?.getDOMNode().removeAttribute 'disabled'
@props.onValid? event, @
else
@refs.submit?.getDOMNode().setAttribute 'disabled', true
@props.onError? event, @
# -- Render
render: ->
className = "#{localCSS.root} #{@props.className}"
<form data-react-toolbox='form' className={className}
onChange={@onChange} onSubmit={@onSubmit}>
{
for attribute, index in @state.attributes
if attribute.type is 'submit'
<Button key={index} {...attribute} type='square' ref='submit' onClick={@onSubmit}/>
else if attribute.type is 'autocomplete'
<Autocomplete key={index} {...attribute} onChange={@onChange}/>
else if attribute.type is 'dropdown'
<Dropdown key={index} {...attribute} onChange={@onChange}/>
else if attribute.type is 'switch'
<Switch key={index} {...attribute} onChange={@onChange}/>
else
<Input key={index} {...attribute} />
}
{ @props.children }
</form>
# -- Extends
storage: (props, value) ->
key = "react-toolbox-form-#{props.storage}"
if value
store = {}
store[attr.ref] = value[attr.ref] for attr in props.attributes when attr.storage
window.localStorage.setItem key, JSON.stringify store
else if props.storage
store = JSON.parse window.localStorage.getItem key or {}
input.value = store?[input.ref] or input.value for input in props.attributes
props.attributes
getValue: ->
value = {}
for ref, el of @refs when el.getValue?
if ref.indexOf('.') is -1
value[ref] = el.getValue()
else
parent = value
for attr, index in hierarchy = ref.split('.')
if index is hierarchy.length - 1
parent[attr] = el.getValue()
else
parent[attr] = parent[attr] or {}
parent = parent[attr]
value
setValue: (data = {}) ->
@refs[field.ref].setValue? field.value for field in data

159
components/form/index.jsx Normal file
View File

@ -0,0 +1,159 @@
/* global React */
import { addons } from 'react/addons';
import style from './style';
import Autocomplete from '../autocomplete';
import Dropdown from '../dropdown';
import Button from '../button';
import Input from '../input';
import Switch from '../switch';
export default React.createClass({
mixins: [addons.PureRenderMixin],
displayName: 'Form',
propTypes: {
attributes: React.PropTypes.array,
className: React.PropTypes.string,
onChange: React.PropTypes.func,
onError: React.PropTypes.func,
onSubmit: React.PropTypes.func,
onValid: React.PropTypes.func,
storage: React.PropTypes.string
},
getDefaultProps () {
return {
attributes: [],
className: ''
};
},
getInitialState () {
return {
attributes: this.storage(this.props)
};
},
componentWillReceiveProps (next_props) {
if (next_props.attributes) {
let attributes = this.storage(next_props);
this.setState({attributes: attributes});
this.setValue(attributes.map((item) => { return item; }));
}
},
onSubmit (event) {
event.preventDefault();
if (this.props.onSubmit) {
this.props.onSubmit(event, this);
}
},
onChange (event) {
let is_valid = true;
let value = this.getValue();
for (let attr of this.state.attributes) {
if (attr.required && value[attr.ref] !== undefined && value[attr.ref].trim() === '') {
is_valid = false;
console.log('NOT VALUD');
if (this.refs[attr.ref].setError) this.refs[attr.ref].setError('Requited field');
break;
}
}
if (this.props.onChange) this.props.onChange(event, this);
if (this.props.storage) this.storage(this.props, value);
if (is_valid) {
if (this.refs.submit) this.refs.submit.getDOMNode().removeAttribute('disabled');
if (this.props.onValid) this.props.onValid(event, this);
} else {
if (this.refs.submit) this.refs.submit.getDOMNode().setAttribute('disabled', true);
if (this.props.onError) this.props.onError(event, this);
}
},
render () {
let className = `${style.root} ${this.props.className}`;
const attributes = this.state.attributes.map((attribute, index) => {
if (attribute.type === 'submit') {
return <Button key={index} {...attribute} type='square' ref='submit' onClick={this.onSubmit}/>;
} else if (attribute.type === 'autocomplete') {
return <Autocomplete key={index} {...attribute} onChange={this.onChange}/>;
} else if (attribute.type === 'dropdown') {
return <Dropdown key={index} {...attribute} onChange={this.onChange}/>;
} else if (attribute.type === 'switch') {
return <Switch key={index} {...attribute} onChange={this.onChange}/>;
} else {
return <Input key={index} {...attribute} />;
}
});
return (
<form
data-react-toolbox='form'
className={className}
onChange={this.onChange}
onSubmit={this.onSubmit}
>
{ attributes }
{ this.props.children }
</form>
);
},
storage (props, value) {
let key = `react-toolbox-form-${props.storage}`;
if (value) {
let store = {};
for (let attr of props.attributes) {
if (attr.storage) store[attr.ref] = value[attr.ref];
}
window.localStorage.setItem(key, JSON.stringify(store));
} else if (props.storage) {
let store = JSON.parse(window.localStorage.getItem(key) || {});
for (let input of props.attributes) {
if (store && store[input.ref]) {
input.value = store[input.ref];
}
}
}
return props.attributes;
},
getValue () {
let value = {};
for (let ref of Object.keys(this.refs)) {
let el = this.refs[ref];
if (el.getValue) {
if (ref.indexOf('.') === -1) {
value[ref] = el.getValue();
} else {
let parent = value;
let hierarchy = ref.split('.');
hierarchy.forEach((attr, index) => {
if (index === hierarchy.length - 1) {
parent[attr] = el.getValue();
} else {
parent[attr] = parent[attr] || {};
parent = parent[attr];
}
});
}
}
}
return value;
},
setValue (data = {}) {
for (let field of data) {
if (this.refs[field.ref].setValue) {
this.refs[field.ref].setValue(field.value);
}
}
}
});

View File

@ -34,7 +34,7 @@ module.exports = React.createClass
,
ref: "type_user", type: "dropdown", label: "Type of user", dataSource: [{value: 1, label: "Normal"}, {value: 2, label: "Root"}]
,
type: "submit", caption: "Send", style: "primary anchor", disabled: true
type: "submit", label: "Send", style: "primary anchor", disabled: true
]
# -- Events