/
WrappedInput.js
148 lines (126 loc) · 3.77 KB
/
WrappedInput.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// react-bootstrap form input with redux-forms
// pass into redux-forms field
// <Field component={ WrappedInput } />
/*
Required props:
name: String: Name of form field
placeholder: String
type: String: Type of form field
label: String: (Optional) Input label
componentClass: (Optional) pass 'textarea' if you wish to have a textarea
*/
import classNames from 'classnames'
import { isEmpty, isFunction, pick, without } from 'lodash'
import React, {
Component,
PropTypes
} from 'react'
import {
FormGroup,
InputGroup,
FormControl,
ControlLabel,
HelpBlock
} from 'react-bootstrap'
export const ROOT_CLASS = 'redux-form-wrapped-input'
export const ERROR_CHILD_CLASS = `${ROOT_CLASS}-error`
export const HELP_TEXT_CHILD_CLASS = `${ROOT_CLASS}-help-text`
export default class WrappedInput extends Component {
render() {
const {
className,
disabled,
helpText,
componentClass,
addonAfter, addonBefore,
showFeedback, showSuccess,
input, label, type, placeholder,
meta: { error, pristine, touched }
} = this.props
const shouldShowFeedback = (
!error && // there are no errors
showFeedback && // the flag is true
(touched || pristine) && // field is touched or form is pristine
!isEmpty(input.value) // the value is not empty
)
const validationState = !error ? (
(showSuccess && !isEmpty(input.value)) ? 'success' : null // highlight valid non-empty values
) : (touched ? 'error' : null) // highlight touched invalid values
let inputProps = {}
if (isFunction(componentClass) && componentClass.propTypes)
inputProps = pick(this.props, without(Object.keys(componentClass.propTypes), 'className'))
return(
<FormGroup className={ classNames(ROOT_CLASS, className) }
validationState={ validationState }
>
{ (touched && error) ? (
<HelpBlock className="pull-right">
{ error }
</HelpBlock>
) : null }
{ input.name && label ? (
<ControlLabel htmlFor={ input.name }>
{ label }
</ControlLabel>
) : null }
{ helpText ? (
<HelpBlock className={ HELP_TEXT_CHILD_CLASS } componentClass="p">
{ helpText }
</HelpBlock>
) : null }
<InputGroup>
{ addonBefore ? (
<InputGroup.Addon>
{ addonBefore }
</InputGroup.Addon>
) : null }
<FormControl
componentClass={ componentClass }
label={ label }
placeholder={ placeholder }
type={ type }
disabled={ disabled }
{ ...inputProps }
{ ...input }
/>
{ addonAfter ? (
<InputGroup.Addon>
{ addonAfter }
</InputGroup.Addon>
) : null }
{ shouldShowFeedback ? (
<FormControl.Feedback>
TODO: Add feedback icon
</FormControl.Feedback>
) : null }
</InputGroup>
</FormGroup>
)
}
}
WrappedInput.defaultProps = {
componentClass: 'input',
showSuccess: true
}
WrappedInput.propTypes = {
addonAfter: PropTypes.node,
addonBefore: PropTypes.node,
className: PropTypes.string,
disabled: PropTypes.bool,
componentClass: PropTypes.oneOfType([ PropTypes.string, PropTypes.func ]),
helpText: PropTypes.string,
input: PropTypes.shape({
name: PropTypes.string.isRequired,
value: PropTypes.any
}).isRequired,
label: PropTypes.string,
meta: PropTypes.shape({
error: PropTypes.string,
pristine: PropTypes.bool,
touched: PropTypes.bool
}),
placeholder: PropTypes.string,
showFeedback: PropTypes.bool,
showSuccess: PropTypes.bool,
type: PropTypes.string
}