Skip to content

Commit 576827f

Browse files
committed
[changed] Introducing ButtonInput
Encapsulating types "button", "reset" and "submit" into a single component. Usage of these types with Input is now deprecated. Please use ButtonInput instead.
1 parent 659976c commit 576827f

File tree

5 files changed

+368
-242
lines changed

5 files changed

+368
-242
lines changed

src/ButtonInput.js

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import React from 'react';
2+
import Button from './Button';
3+
import FormGroup from './FormGroup';
4+
import InputBase from './InputBase';
5+
6+
function valueValidation({children, value}, propName, componentName) {
7+
if (children && value) {
8+
return new Error('Both value and children cannot be passed to ButtonInput');
9+
}
10+
return React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.number]).call(null, {children, value}, propName, componentName);
11+
}
12+
13+
class ButtonInput extends InputBase {
14+
renderFormGroup(children) {
15+
let {bsStyle, value, ...other} = this.props; /* eslint no-unused-vars: 0 object-shorthand: 0 */
16+
return <FormGroup {...other}>{children}</FormGroup>;
17+
}
18+
19+
renderInput() {
20+
let {children, value, ...other} = this.props;
21+
let val = children ? children : value;
22+
return <Button {...other} componentClass="input" ref="input" key="input" value={val} />;
23+
}
24+
}
25+
26+
ButtonInput.defaultProps = {
27+
type: 'button'
28+
};
29+
30+
ButtonInput.propTypes = {
31+
type: React.PropTypes.oneOf(['button', 'reset', 'submit']),
32+
bsStyle(props) {
33+
//defer to Button propTypes of bsStyle
34+
return null;
35+
},
36+
children: valueValidation,
37+
value: valueValidation
38+
};
39+
40+
export default ButtonInput;

src/Input.js

+10-230
Original file line numberDiff line numberDiff line change
@@ -1,239 +1,19 @@
11
import React from 'react';
2-
import classNames from 'classnames';
3-
import Button from './Button';
4-
import FormGroup from './FormGroup';
2+
import InputBase from './InputBase';
3+
import ButtonInput from './ButtonInput';
4+
import deprecationWarning from './utils/deprecationWarning';
55

6-
class Input extends React.Component {
7-
getInputDOMNode() {
8-
return React.findDOMNode(this.refs.input);
9-
}
10-
11-
getValue() {
12-
if (this.props.type === 'static') {
13-
return this.props.value;
14-
} else if (this.props.type) {
15-
if (this.props.type === 'select' && this.props.multiple) {
16-
return this.getSelectedOptions();
17-
} else {
18-
return this.getInputDOMNode().value;
19-
}
20-
} else {
21-
throw 'Cannot use getValue without specifying input type.';
22-
}
23-
}
24-
25-
getChecked() {
26-
return this.getInputDOMNode().checked;
27-
}
28-
29-
getSelectedOptions() {
30-
let values = [];
31-
32-
Array.prototype.forEach.call(
33-
this.getInputDOMNode().getElementsByTagName('option'),
34-
(option) => {
35-
if (option.selected) {
36-
let value = option.getAttribute('value') || option.innerHtml;
37-
values.push(value);
38-
}
39-
});
40-
41-
return values;
42-
}
43-
44-
isCheckboxOrRadio() {
45-
return this.props.type === 'checkbox' || this.props.type === 'radio';
46-
}
47-
48-
isFile() {
49-
return this.props.type === 'file';
50-
}
51-
52-
renderInputGroup(children) {
53-
let addonBefore = this.props.addonBefore ? (
54-
<span className="input-group-addon" key="addonBefore">
55-
{this.props.addonBefore}
56-
</span>
57-
) : null;
58-
59-
let addonAfter = this.props.addonAfter ? (
60-
<span className="input-group-addon" key="addonAfter">
61-
{this.props.addonAfter}
62-
</span>
63-
) : null;
64-
65-
let buttonBefore = this.props.buttonBefore ? (
66-
<span className="input-group-btn">
67-
{this.props.buttonBefore}
68-
</span>
69-
) : null;
70-
71-
let buttonAfter = this.props.buttonAfter ? (
72-
<span className="input-group-btn">
73-
{this.props.buttonAfter}
74-
</span>
75-
) : null;
76-
77-
let inputGroupClassName;
78-
switch (this.props.bsSize) {
79-
case 'small': inputGroupClassName = 'input-group-sm'; break;
80-
case 'large': inputGroupClassName = 'input-group-lg'; break;
81-
}
82-
83-
return addonBefore || addonAfter || buttonBefore || buttonAfter ? (
84-
<div className={classNames(inputGroupClassName, 'input-group')} key="input-group">
85-
{addonBefore}
86-
{buttonBefore}
87-
{children}
88-
{addonAfter}
89-
{buttonAfter}
90-
</div>
91-
) : children;
92-
}
93-
94-
renderIcon() {
95-
let classes = {
96-
'glyphicon': true,
97-
'form-control-feedback': true,
98-
'glyphicon-ok': this.props.bsStyle === 'success',
99-
'glyphicon-warning-sign': this.props.bsStyle === 'warning',
100-
'glyphicon-remove': this.props.bsStyle === 'error'
101-
};
102-
103-
return this.props.hasFeedback ? (
104-
<span className={classNames(classes)} key="icon" />
105-
) : null;
106-
}
6+
const buttonTypes = ['button', 'reset', 'submit'];
1077

108-
renderHelp() {
109-
return this.props.help ? (
110-
<span className="help-block" key="help">
111-
{this.props.help}
112-
</span>
113-
) : null;
114-
}
115-
116-
renderCheckboxAndRadioWrapper(children) {
117-
let classes = {
118-
'checkbox': this.props.type === 'checkbox',
119-
'radio': this.props.type === 'radio'
120-
};
121-
122-
return (
123-
<div className={classNames(classes)} key="checkboxRadioWrapper">
124-
{children}
125-
</div>
126-
);
127-
}
128-
129-
renderWrapper(children) {
130-
return this.props.wrapperClassName ? (
131-
<div className={this.props.wrapperClassName} key="wrapper">
132-
{children}
133-
</div>
134-
) : children;
135-
}
136-
137-
renderLabel(children) {
138-
let classes = {
139-
'control-label': !this.isCheckboxOrRadio()
140-
};
141-
classes[this.props.labelClassName] = this.props.labelClassName;
142-
143-
return this.props.label ? (
144-
<label htmlFor={this.props.id} className={classNames(classes)} key="label">
145-
{children}
146-
{this.props.label}
147-
</label>
148-
) : children;
149-
}
150-
151-
renderInput() {
152-
if (!this.props.type) {
153-
return this.props.children;
154-
}
155-
156-
switch (this.props.type) {
157-
case 'select':
158-
return (
159-
<select {...this.props} className={classNames(this.props.className, 'form-control')} ref="input" key="input">
160-
{this.props.children}
161-
</select>
162-
);
163-
case 'textarea':
164-
return <textarea {...this.props} className={classNames(this.props.className, 'form-control')} ref="input" key="input" />;
165-
case 'static':
166-
return (
167-
<p {...this.props} className={classNames(this.props.className, 'form-control-static')} ref="input" key="input">
168-
{this.props.value}
169-
</p>
170-
);
171-
case 'submit':
172-
return <Button {...this.props} componentClass="input" ref="input" key="input" />;
173-
}
174-
175-
let className = this.isCheckboxOrRadio() || this.isFile() ? '' : 'form-control';
176-
return <input {...this.props} className={classNames(this.props.className, className)} ref="input" key="input" />;
177-
}
178-
179-
renderFormGroup(children) {
180-
if (this.props.type === 'submit') {
181-
let {bsStyle, ...other} = this.props; /* eslint no-unused-vars: 0 object-shorthand: 0 */
182-
return <FormGroup {...other}>{children}</FormGroup>;
8+
class Input extends InputBase {
9+
render() {
10+
if (buttonTypes.indexOf(this.props.type) > -1) {
11+
deprecationWarning(`Input type=${this.props.type}`, 'ButtonInput');
12+
return <ButtonInput {...this.props} />;
18313
}
18414

185-
return <FormGroup {...this.props}>{children}</FormGroup>;
186-
}
187-
188-
renderChildren() {
189-
return !this.isCheckboxOrRadio() ? [
190-
this.renderLabel(),
191-
this.renderWrapper([
192-
this.renderInputGroup(
193-
this.renderInput()
194-
),
195-
this.renderIcon(),
196-
this.renderHelp()
197-
])
198-
] : this.renderWrapper([
199-
this.renderCheckboxAndRadioWrapper(
200-
this.renderLabel(
201-
this.renderInput()
202-
)
203-
),
204-
this.renderHelp()
205-
]);
206-
}
207-
208-
render() {
209-
let children = this.renderChildren();
210-
return this.renderFormGroup(children);
15+
return super.render();
21116
}
21217
}
21318

214-
Input.propTypes = {
215-
type: React.PropTypes.string,
216-
label: React.PropTypes.node,
217-
help: React.PropTypes.node,
218-
addonBefore: React.PropTypes.node,
219-
addonAfter: React.PropTypes.node,
220-
buttonBefore: React.PropTypes.node,
221-
buttonAfter: React.PropTypes.node,
222-
bsSize: React.PropTypes.oneOf(['small', 'medium', 'large']),
223-
bsStyle(props) {
224-
if (props.type === 'submit') {
225-
return null;
226-
}
227-
return React.PropTypes.oneOf(['success', 'warning', 'error']).apply(null, arguments);
228-
},
229-
hasFeedback: React.PropTypes.bool,
230-
id: React.PropTypes.string,
231-
groupClassName: React.PropTypes.string,
232-
wrapperClassName: React.PropTypes.string,
233-
labelClassName: React.PropTypes.string,
234-
multiple: React.PropTypes.bool,
235-
disabled: React.PropTypes.bool,
236-
value: React.PropTypes.any
237-
};
238-
23919
export default Input;

0 commit comments

Comments
 (0)