2017-07-10 17:55:46 +02:00
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* InputNumber
|
2017-07-11 15:39:00 +02:00
|
|
|
* Customization
|
|
|
|
|
* - deactivateErrorHighlight: bool
|
|
|
|
|
* allow the user to remove bootstrap class 'has-danger' on the inputText
|
|
|
|
|
* - customBootstrapClass : string
|
|
|
|
|
* overrides the default 'col-md-6' on the inputText
|
|
|
|
|
* - handleBlur: function
|
|
|
|
|
* overrides the default input validations
|
|
|
|
|
* - errors : array
|
|
|
|
|
* custom errors if set to false it deactivate error display
|
|
|
|
|
*
|
|
|
|
|
* Required
|
|
|
|
|
* - name : string
|
|
|
|
|
* - handleChange : function
|
|
|
|
|
* - value : string
|
|
|
|
|
* - validations : object
|
|
|
|
|
*
|
|
|
|
|
* Optionnal
|
|
|
|
|
* - description : input description
|
|
|
|
|
* - handleFocus : function
|
|
|
|
|
* - placeholder : string if set to "" nothing will display
|
2017-07-10 17:55:46 +02:00
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import React from 'react';
|
2017-07-12 18:12:07 +02:00
|
|
|
import { isEmpty, map, pick } from 'lodash';
|
2017-07-10 17:55:46 +02:00
|
|
|
import styles from './styles.scss';
|
|
|
|
|
|
|
|
|
|
class InputNumber extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
|
|
|
|
constructor(props) {
|
|
|
|
|
super(props);
|
|
|
|
|
this.state = {
|
|
|
|
|
errors: false,
|
2017-07-11 15:39:00 +02:00
|
|
|
hasInitialValue: false,
|
2017-07-10 17:55:46 +02:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-11 15:39:00 +02:00
|
|
|
componentDidMount() {
|
|
|
|
|
if (this.props.value && this.props.value.length !== '') {
|
|
|
|
|
this.setState({ hasInitialValue: true });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-10 17:55:46 +02:00
|
|
|
componentWillReceiveProps(nextProps) {
|
|
|
|
|
if (this.props.errors !== nextProps.errors) {
|
2017-07-11 15:42:54 +02:00
|
|
|
let errors = false;
|
2017-07-12 18:12:07 +02:00
|
|
|
if (isEmpty(nextProps.errors)) {
|
2017-07-11 15:42:54 +02:00
|
|
|
errors = nextProps.errors === true ? [] : false;
|
|
|
|
|
} else {
|
|
|
|
|
errors = nextProps.errors;
|
|
|
|
|
}
|
2017-07-10 17:55:46 +02:00
|
|
|
this.setState({ errors });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
handleBlur = ({ target }) => {
|
2017-07-11 15:39:00 +02:00
|
|
|
// prevent error display if input is initially empty
|
|
|
|
|
if (target.value.length > 0 || this.state.hasInitialValue) {
|
|
|
|
|
// validates basic string validations
|
|
|
|
|
// add custom logic here such as alerts...
|
|
|
|
|
const errors = this.validate(target.value);
|
2017-07-11 15:42:54 +02:00
|
|
|
this.setState({ errors, hasInitialValue: true });
|
2017-07-11 15:39:00 +02:00
|
|
|
}
|
2017-07-10 17:55:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
validate = (value) => {
|
2017-07-12 18:12:07 +02:00
|
|
|
const errors = !isEmpty(pick(this.props.validations, 'required')) && value.length > 0 ?
|
2017-07-10 17:55:46 +02:00
|
|
|
false : ['This field is required'];
|
|
|
|
|
return errors;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
render() {
|
|
|
|
|
const inputValue = this.props.value || '';
|
|
|
|
|
// override default onBlur
|
|
|
|
|
const handleBlur = this.props.handleBlur || this.handleBlur;
|
|
|
|
|
// override bootStrapClass
|
2017-07-11 15:39:00 +02:00
|
|
|
const bootStrapClass = this.props.customBootstrapClass ? this.props.customBootstrapClass : 'col-md-4';
|
2017-07-10 17:55:46 +02:00
|
|
|
// set error class with override possibility
|
2017-07-11 15:39:00 +02:00
|
|
|
const bootStrapClassDanger = !this.props.deactivateErrorHighlight && this.state.errors ? 'has-danger' : '';
|
2017-07-10 17:55:46 +02:00
|
|
|
const placeholder = this.props.placeholder || `Change ${this.props.name} field`;
|
|
|
|
|
return (
|
|
|
|
|
<div className={`${styles.inputNumber} ${bootStrapClass} ${bootStrapClassDanger}`}>
|
2017-07-11 15:42:54 +02:00
|
|
|
<label htmlFor={this.props.name}>{this.props.name}</label>
|
2017-07-10 17:55:46 +02:00
|
|
|
<input
|
|
|
|
|
type="number"
|
2017-07-11 15:42:54 +02:00
|
|
|
name={this.props.name}
|
|
|
|
|
id={this.props.name}
|
2017-07-11 15:39:00 +02:00
|
|
|
value={inputValue}
|
2017-07-10 17:55:46 +02:00
|
|
|
onBlur={handleBlur}
|
|
|
|
|
onChange={this.props.handleChange}
|
2017-07-11 15:39:00 +02:00
|
|
|
onFocus={this.props.handleFocus}
|
|
|
|
|
className={`form-control ${this.state.errors? 'form-control-danger' : ''}`}
|
2017-07-10 17:55:46 +02:00
|
|
|
placeholder={placeholder}
|
|
|
|
|
/>
|
|
|
|
|
<small>{this.props.inputDescription}</small>
|
2017-07-12 18:12:07 +02:00
|
|
|
{map(this.state.errors, (error, key) => (
|
2017-07-11 15:39:00 +02:00
|
|
|
<div key={key} className="form-control-feedback">{error}</div>
|
2017-07-10 17:55:46 +02:00
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
InputNumber.propTypes = {
|
2017-07-11 15:42:54 +02:00
|
|
|
customBootstrapClass: React.PropTypes.string,
|
|
|
|
|
deactivateErrorHighlight: React.PropTypes.bool,
|
2017-07-10 17:55:46 +02:00
|
|
|
errors: React.PropTypes.oneOfType([
|
|
|
|
|
React.PropTypes.bool,
|
|
|
|
|
React.PropTypes.array,
|
|
|
|
|
]),
|
2017-07-11 15:42:54 +02:00
|
|
|
handleBlur: React.PropTypes.func,
|
2017-07-10 17:55:46 +02:00
|
|
|
handleChange: React.PropTypes.func.isRequired,
|
2017-07-11 15:39:00 +02:00
|
|
|
handleFocus: React.PropTypes.func,
|
2017-07-10 17:55:46 +02:00
|
|
|
inputDescription: React.PropTypes.string,
|
|
|
|
|
name: React.PropTypes.string.isRequired,
|
|
|
|
|
placeholder: React.PropTypes.string,
|
2017-07-11 15:42:54 +02:00
|
|
|
validations: React.PropTypes.object.isRequired,
|
2017-07-10 17:55:46 +02:00
|
|
|
value: React.PropTypes.oneOfType([
|
|
|
|
|
React.PropTypes.number.isRequired,
|
|
|
|
|
React.PropTypes.string.isRequired,
|
|
|
|
|
]),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default InputNumber;
|