2015-06-05 11:06:36 +02:00
|
|
|
'use strict';
|
|
|
|
|
2015-06-01 13:02:53 +02:00
|
|
|
import React from 'react';
|
|
|
|
|
2015-07-28 15:46:55 +02:00
|
|
|
/**
|
|
|
|
* This component can be used as a custom input element for form properties.
|
|
|
|
* It exposes its state via state.value and can be considered as a reference implementation
|
|
|
|
* for custom input components that live inside of properties.
|
|
|
|
*/
|
2015-06-01 13:02:53 +02:00
|
|
|
let InputCheckbox = React.createClass({
|
2015-06-09 16:10:38 +02:00
|
|
|
propTypes: {
|
2015-07-28 12:03:45 +02:00
|
|
|
required: React.PropTypes.bool,
|
2015-07-28 15:46:55 +02:00
|
|
|
|
|
|
|
// As can be read here: https://facebook.github.io/react/docs/forms.html
|
|
|
|
// inputs of type="checkbox" define their state via checked.
|
|
|
|
// Their default state is defined via defaultChecked.
|
|
|
|
//
|
|
|
|
// Since this component even has checkbox in its name, it felt wrong to expose defaultValue
|
|
|
|
// as the default-setting prop to other developers, which is why we choose defaultChecked.
|
2015-07-28 12:03:45 +02:00
|
|
|
defaultChecked: React.PropTypes.bool,
|
2015-07-14 19:53:49 +02:00
|
|
|
children: React.PropTypes.oneOfType([
|
|
|
|
React.PropTypes.arrayOf(React.PropTypes.element),
|
|
|
|
React.PropTypes.element
|
2015-08-19 17:06:14 +02:00
|
|
|
]),
|
2015-10-14 15:30:10 +02:00
|
|
|
name: React.PropTypes.string,
|
2015-08-19 17:06:14 +02:00
|
|
|
|
|
|
|
// provided by Property
|
|
|
|
disabled: React.PropTypes.bool,
|
2015-09-22 16:45:24 +02:00
|
|
|
onChange: React.PropTypes.func,
|
|
|
|
|
|
|
|
// can be used to style the component from the outside
|
|
|
|
style: React.PropTypes.object
|
2015-06-09 16:10:38 +02:00
|
|
|
},
|
2015-07-28 15:33:47 +02:00
|
|
|
|
2015-07-28 15:46:55 +02:00
|
|
|
// As HTML inputs, we're setting the default value for an input to checked === false
|
2015-07-27 14:39:19 +02:00
|
|
|
getDefaultProps() {
|
|
|
|
return {
|
2015-07-28 15:33:47 +02:00
|
|
|
defaultChecked: false
|
2015-07-27 14:39:19 +02:00
|
|
|
};
|
|
|
|
},
|
2015-06-01 13:02:53 +02:00
|
|
|
|
2015-07-28 15:46:55 +02:00
|
|
|
// Setting value to null in initialState is essentially since we're deriving a certain state from
|
|
|
|
// value === null as can be seen in componentWillReceiveProps.
|
2015-06-01 13:02:53 +02:00
|
|
|
getInitialState() {
|
2015-06-05 11:06:36 +02:00
|
|
|
return {
|
2015-07-28 15:33:47 +02:00
|
|
|
value: null
|
2015-06-01 13:02:53 +02:00
|
|
|
};
|
|
|
|
},
|
2015-07-10 15:56:54 +02:00
|
|
|
|
2015-07-28 15:33:47 +02:00
|
|
|
componentWillReceiveProps(nextProps) {
|
2015-07-28 15:46:55 +02:00
|
|
|
|
|
|
|
// Developer's are used to define defaultValues for inputs via defaultValue, but since this is a
|
|
|
|
// input of type checkbox we warn the dev to not do that.
|
2015-10-14 15:49:04 +02:00
|
|
|
if(this.props.defaultValue) { //eslint-disable-line react/prop-types
|
2015-07-28 15:46:55 +02:00
|
|
|
console.warn('InputCheckbox is of type checkbox. Therefore its value is represented by checked and defaultChecked. defaultValue will do nothing!');
|
2015-07-28 15:33:47 +02:00
|
|
|
}
|
|
|
|
|
2015-07-28 15:46:55 +02:00
|
|
|
// The first time InputCheckbox is rendered, we want to set its value to the value of defaultChecked.
|
|
|
|
// This needs to be done in order to expose it for the Property component.
|
|
|
|
// We can determine the first render by checking if value still has it's initialState(from getInitialState)
|
2015-07-28 15:33:47 +02:00
|
|
|
if(this.state.value === null) {
|
2015-07-28 15:46:55 +02:00
|
|
|
this.setState({value: nextProps.defaultChecked });
|
2015-07-28 15:33:47 +02:00
|
|
|
}
|
2015-07-28 12:03:45 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
onChange() {
|
2015-08-19 17:06:14 +02:00
|
|
|
// if this.props.disabled is true, we're just going to ignore every click,
|
|
|
|
// as the value should then not be changable by the user
|
|
|
|
if(this.props.disabled) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-07-28 15:46:55 +02:00
|
|
|
// On every change, we're inversing the input's value
|
2015-07-28 15:33:47 +02:00
|
|
|
let inverseValue = !this.refs.checkbox.getDOMNode().checked;
|
|
|
|
|
2015-07-28 15:46:55 +02:00
|
|
|
// pass it to the state
|
2015-07-28 15:33:47 +02:00
|
|
|
this.setState({value: inverseValue});
|
2015-07-28 15:46:55 +02:00
|
|
|
|
2015-08-19 16:03:59 +02:00
|
|
|
// and also call Property's onChange method
|
|
|
|
// (in this case we're mocking event.target.value, since we can not use the event
|
|
|
|
// coming from onChange. Its coming from the span (user is clicking on the span) and not the input)
|
|
|
|
this.props.onChange({
|
|
|
|
target: {
|
|
|
|
value: inverseValue
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2015-06-01 13:02:53 +02:00
|
|
|
},
|
2015-06-05 11:06:36 +02:00
|
|
|
|
2015-06-01 13:02:53 +02:00
|
|
|
render() {
|
2015-08-19 17:06:14 +02:00
|
|
|
|
|
|
|
let style = {};
|
|
|
|
|
|
|
|
// Some conditional styling if the component is disabled
|
|
|
|
if(!this.props.disabled) {
|
|
|
|
style.cursor = 'pointer';
|
|
|
|
style.color = 'rgba(0, 0, 0, 0.5)';
|
|
|
|
} else {
|
|
|
|
style.cursor = 'not-allowed';
|
|
|
|
style.color = 'rgba(0, 0, 0, 0.35)';
|
|
|
|
}
|
|
|
|
|
2015-06-01 13:02:53 +02:00
|
|
|
return (
|
2015-07-10 15:56:54 +02:00
|
|
|
<span
|
2015-09-22 16:45:24 +02:00
|
|
|
style={this.props.style}
|
2015-10-14 15:30:10 +02:00
|
|
|
onClick={this.onChange}
|
|
|
|
name={this.props.name}>
|
2015-07-27 14:39:19 +02:00
|
|
|
<input
|
2015-10-14 15:30:10 +02:00
|
|
|
name={this.props.name}
|
2015-07-27 14:39:19 +02:00
|
|
|
type="checkbox"
|
|
|
|
ref="checkbox"
|
|
|
|
onChange={this.onChange}
|
2015-07-28 12:03:45 +02:00
|
|
|
checked={this.state.value}
|
|
|
|
defaultChecked={this.props.defaultChecked}/>
|
2015-08-19 17:06:14 +02:00
|
|
|
<span
|
|
|
|
className="checkbox"
|
|
|
|
style={style}>
|
2015-07-14 19:53:49 +02:00
|
|
|
{this.props.children}
|
2015-07-10 15:56:54 +02:00
|
|
|
</span>
|
|
|
|
</span>
|
2015-06-01 13:02:53 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2015-10-14 15:30:10 +02:00
|
|
|
export default InputCheckbox;
|