264 lines
8.9 KiB
JavaScript
Raw Normal View History

/**
*
* Input
*
*/
import React from 'react';
import { get, isEmpty, map, isObject } from 'lodash';
import { FormattedMessage } from 'react-intl';
import styles from './styles.scss';
class Input extends React.Component { // eslint-disable-line react/prefer-stateless-function
constructor(props) {
super(props);
this.state = {
errors: [],
hasInitialValue: false,
};
}
componentDidMount() {
// Init the select value if type === "select"
if (this.props.type === 'select' && !isEmpty(this.props.selectOptions) && this.props.selectOptions[0].value !== '') {
const target = { name: this.props.target, value: this.props.selectOptions[0].value };
this.props.handleChange({ target });
}
}
componentWillReceiveProps(nextProps) {
if (this.props.type === 'select' && this.props.selectOptionsFetchSucceeded !== nextProps.selectOptionsFetchSucceeded && nextProps.selectOptions[0].value !== '') {
const target = { name: nextProps.target, value: nextProps.selectOptions[0].value };
this.props.handleChange({ target });
}
}
handleChangeCheckbox = (e) => {
const target = {
type: e.target.type,
value: !this.props.value,
name: e.target.name,
};
this.props.handleChange({ target });
}
renderErrors = (errorStyles) => { // eslint-disable-line consistent-return
if (!this.props.noErrorsDescription) {
const divStyle = errorStyles || styles.errorContainer;
return (
map(this.state.errors, (error, key) => {
const displayError = isObject(error) && error.id
? <FormattedMessage {...error} />
: error;
return (
<div key={key} className={`form-control-feedback ${divStyle}`}>{displayError}</div>
);
})
);
}
}
renderInputCheckbox = (requiredClass, inputDescription) => {
const title = !isEmpty(this.props.title) ? <div className={styles.inputTitle}><FormattedMessage id={this.props.title} /></div> : '';
const spacer = !inputDescription ? <div /> : <div style={{ marginBottom: '.5rem'}}></div>;
return (
<div className={`${styles.inputCheckbox} col-md-12 ${requiredClass}`}>
<div className="form-check">
{title}
<FormattedMessage id={this.props.name}>
{(message) => (
<label className={`${styles.checkboxLabel} form-check-label`} htmlFor={this.props.name}>
<input className="form-check-input" type="checkbox" checked={this.props.value} onChange={this.handleChangeCheckbox} name={this.props.target} />
{message}
</label>
)}
</FormattedMessage>
<div className={styles.inputCheckboxDescriptionContainer}>
<small>{inputDescription}</small>
</div>
</div>
{spacer}
</div>
)
}
renderInputSelect = (bootStrapClass, requiredClass, inputDescription) => {
const spacer = !isEmpty(this.props.inputDescription) ? <div className={styles.spacer} /> : <div />;
return (
<div className={`${styles.input} ${requiredClass} ${bootStrapClass}`}>
<label htmlFor={this.props.name}>
<FormattedMessage id={`${this.props.name}`} />
</label>
<select
className="form-control"
id={this.props.name}
name={this.props.target}
onChange={this.props.handleChange}
value={this.props.value}
>
{map(this.props.selectOptions, (option, key) => (
<FormattedMessage id={`${option.name}`} key={key}>
{(message) => (
<option value={option.value}>
{message}
</option>
)}
</FormattedMessage>
))}
</select>
<div className={styles.inputDescriptionContainer}>
<small>{inputDescription}</small>
</div>
{spacer}
</div>
);
}
renderInputTextArea = (bootStrapClass, requiredClass, bootStrapClassDanger, inputDescription) => {
let spacer = !isEmpty(this.props.inputDescription) ? <div className={styles.spacer} /> : <div />;
if (!this.props.noErrorsDescription && !isEmpty(this.state.errors)) {
spacer = <div />;
}
return (
<div className={`${styles.inputTextArea} ${bootStrapClass} ${requiredClass} ${bootStrapClassDanger}`}>
<label htmlFor={this.props.name}>
<FormattedMessage id={`${this.props.name}`} />
</label>
<FormattedMessage id={this.props.placeholder || this.props.name}>
{(placeholder) => (
<textarea
className="form-control"
onChange={this.props.handleChange}
value={this.props.value}
name={this.props.target}
id={this.props.name}
placeholder={placeholder}
/>
)}
</FormattedMessage>
<div className={styles.inputTextAreaDescriptionContainer}>
<small>{inputDescription}</small>
</div>
{this.renderErrors(styles.errorContainerTextArea)}
{spacer}
</div>
)
}
renderFormattedInput = (handleBlur, inputValue, placeholder) => (
<FormattedMessage id={`${placeholder}`}>
{(message) => (
<input
name={this.props.target}
id={this.props.name}
onBlur={handleBlur}
onFocus={this.props.handleFocus}
onChange={this.props.handleChange}
value={inputValue}
type={this.props.type}
className={`form-control ${this.state.errors? 'form-control-danger' : ''}`}
placeholder={message}
autoComplete="off"
/>
)}
</FormattedMessage>
)
render() {
const inputValue = this.props.value || '';
// override default onBlur
const handleBlur = this.props.handleBlur || this.handleBlur;
// override bootStrapClass
const bootStrapClass = this.props.customBootstrapClass ? this.props.customBootstrapClass : 'col-md-6';
// set error class with override possibility
const bootStrapClassDanger = !this.props.deactivateErrorHighlight && !isEmpty(this.state.errors) ? 'has-danger' : '';
const placeholder = this.props.placeholder || this.props.name;
const label = this.props.name ?
<label htmlFor={this.props.name}><FormattedMessage id={`${this.props.name}`} /></label>
: <label htmlFor={this.props.name} />;
const requiredClass = get(this.props.validations, 'required') && this.props.addRequiredInputDesign ?
styles.requiredClass : '';
const input = placeholder ? this.renderFormattedInput(handleBlur, inputValue, placeholder)
: <input
name={this.props.target}
id={this.props.name}
onBlur={handleBlur}
onFocus={this.props.handleFocus}
onChange={this.props.handleChange}
value={inputValue}
type={this.props.type}
className={`form-control ${this.state.errors? 'form-control-danger' : ''}`}
placeholder={placeholder}
/>;
const inputDescription = !isEmpty(this.props.inputDescription) ? <FormattedMessage id={this.props.inputDescription} /> : '';
let spacer = !isEmpty(this.props.inputDescription) ? <div className={styles.spacer} /> : <div />;
if (!this.props.noErrorsDescription && !isEmpty(this.state.errors)) {
spacer = <div />;
}
switch (this.props.type) {
case 'select':
return this.renderInputSelect(bootStrapClass, requiredClass, inputDescription);
case 'textarea':
return this.renderInputTextArea(bootStrapClass, requiredClass, bootStrapClassDanger, inputDescription);
case 'checkbox':
return this.renderInputCheckbox(requiredClass, inputDescription);
default:
}
return (
<div className={`${styles.input} ${bootStrapClass} ${requiredClass} ${bootStrapClassDanger}`}>
{label}
{input}
<div className={styles.inputDescriptionContainer}>
<small>{inputDescription}</small>
</div>
{this.renderErrors()}
{spacer}
</div>
);
}
}
Input.propTypes = {
addRequiredInputDesign: React.PropTypes.bool,
customBootstrapClass: React.PropTypes.string,
deactivateErrorHighlight: React.PropTypes.bool,
// errors: React.PropTypes.array,
handleBlur: React.PropTypes.func,
handleChange: React.PropTypes.func.isRequired,
handleFocus: React.PropTypes.func,
inputDescription: React.PropTypes.string,
name: React.PropTypes.string.isRequired,
noErrorsDescription: React.PropTypes.bool,
placeholder: React.PropTypes.string,
// styles: React.PropTypes.object,
selectOptions: React.PropTypes.array,
selectOptionsFetchSucceeded: React.PropTypes.bool,
target: React.PropTypes.string,
title: React.PropTypes.string,
type: React.PropTypes.string.isRequired,
validations: React.PropTypes.object.isRequired,
value: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.bool,
React.PropTypes.number,
]),
};
export default Input;