Skip to content

Commit

Permalink
[added] standalone prop to Input, which will not render the `form-g…
Browse files Browse the repository at this point in the history
…roup` class

In some cases you may not want the `form-group` class applied to form
input wrapper divs. To achieve this simply apply the `standalone` prop.

Fixes react-bootstrap#205
  • Loading branch information
mtscout6 committed Mar 27, 2015
1 parent 7d7e465 commit bfb3e6c
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 30 deletions.
2 changes: 1 addition & 1 deletion docs/src/ComponentsPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,7 @@ const ComponentsPage = React.createClass({
<h1 id='input' className='page-header'>Input</h1>
<p>Renders an input in bootstrap wrappers. Supports label, help, text input add-ons, validation and use as wrapper.
Use <code>getValue()</code> or <code>getChecked()</code> to get the current state.
The helper method <code>getInputDOMNode()</code> returns the internal input element.</p>
The helper method <code>getInputDOMNode()</code> returns the internal input element. If you don't want the <code>form-group</code> class applied apply the prop named <code>standalone</code>.</p>
<ReactPlayground codeText={Samples.Input} />
<h2 id='input-types'>Types</h2>
<p>Supports <code>select</code>, <code>textarea</code>, <code>static</code> as well as standard HTML input types. <code>getValue()</code> returns an array for multiple select.</p>
Expand Down
33 changes: 33 additions & 0 deletions src/FormGroup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from 'react';
import classSet from 'classnames';

class FormGroup extends React.Component {
render() {
let classes = {
'form-group': !this.props.standalone,
'has-feedback': this.props.hasFeedback,
'has-success': this.props.bsStyle === 'success',
'has-warning': this.props.bsStyle === 'warning',
'has-error': this.props.bsStyle === 'error'
};

return (
<div className={classSet(classes, this.props.groupClassName)}>
{this.props.children}
</div>
);
}
}

FormGroup.defaultProps = {
standalone: false
};

FormGroup.propTypes = {
standalone: React.PropTypes.bool,
hasFeedback: React.PropTypes.bool,
bsStyle: React.PropTypes.oneOf(['success', 'warning', 'error']),
groupClassName: React.PropTypes.string
};

export default FormGroup;
44 changes: 15 additions & 29 deletions src/Input.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import classSet from 'classnames';
import Button from './Button';
import FormGroup from './FormGroup';

const Input = React.createClass({

Expand Down Expand Up @@ -215,38 +216,21 @@ const Input = React.createClass({
) : children;
},

renderFormGroup(children) {
let classes = {
'form-group': true,
'has-feedback': this.props.hasFeedback,
'has-success': this.props.bsStyle === 'success',
'has-warning': this.props.bsStyle === 'warning',
'has-error': this.props.bsStyle === 'error'
};
classes[this.props.groupClassName] = this.props.groupClassName;

return (
<div className={classSet(classes)}>
{children}
</div>
);
},

render() {
let children;

if (this.isCheckboxOrRadio()) {
return this.renderFormGroup(
this.renderWrapper([
this.renderCheckboxandRadioWrapper(
this.renderLabel(
this.renderInput()
)
),
this.renderHelp()
])
);
children = this.renderWrapper([
this.renderCheckboxandRadioWrapper(
this.renderLabel(
this.renderInput()
)
),
this.renderHelp()
]);
}
else {
return this.renderFormGroup([
children = [
this.renderLabel(),
this.renderWrapper([
this.renderInputGroup(
Expand All @@ -255,8 +239,10 @@ const Input = React.createClass({
this.renderIcon(),
this.renderHelp()
])
]);
];
}

return <FormGroup {...this.props}>{children}</FormGroup>;
}
});

Expand Down
86 changes: 86 additions & 0 deletions test/FormGroupSpec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import React from 'react';
import ReactTestUtils from 'react/lib/ReactTestUtils';
import FormGroup from '../src/FormGroup';

describe('FormGroup', function() {
beforeEach(function() {
sinon.spy(console, 'warn');
});

afterEach(function() {
if (typeof console.warn.restore === 'function') {
console.warn.called.should.be.false;
console.warn.restore();
}
});

it('renders children', function() {
let instance = ReactTestUtils.renderIntoDocument(
<FormGroup>
<span className='child1' />
<span className='child2' />
</FormGroup>
);

assert.ok(ReactTestUtils.findRenderedDOMComponentWithClass(instance, 'child1'));
assert.ok(ReactTestUtils.findRenderedDOMComponentWithClass(instance, 'child2'));
});

it('renders with form-group class', function() {
let instance = ReactTestUtils.renderIntoDocument(
<FormGroup>
<span />
</FormGroup>
);

assert.ok(ReactTestUtils.findRenderedDOMComponentWithClass(instance, 'form-group'));
});

it('renders no form-group class when standalone', function() {
let instance = ReactTestUtils.renderIntoDocument(
<FormGroup standalone>
<span />
</FormGroup>
);

assert.equal(ReactTestUtils.scryRenderedDOMComponentsWithClass(instance, 'form-group').length, 0);
});

[{
className: 'has-feedback',
props: { hasFeedback: true }
}, {
className: 'has-success',
props: { bsStyle: 'success' }
}, {
className: 'has-warning',
props: { bsStyle: 'warning' }
}, {
className: 'has-error',
props: { bsStyle: 'error' }
}, {
className: 'custom-group',
props: { groupClassName: 'custom-group' }
}
].forEach(function(testCase) {
it(`does not render ${testCase.className} class`, function() {
let instance = ReactTestUtils.renderIntoDocument(
<FormGroup>
<span />
</FormGroup>
);

assert.equal(ReactTestUtils.scryRenderedDOMComponentsWithClass(instance, testCase.className).length, 0);
});

it(`renders with ${testCase.className} class`, function() {
let instance = ReactTestUtils.renderIntoDocument(
<FormGroup {...testCase.props}>
<span />
</FormGroup>
);

assert.ok(ReactTestUtils.findRenderedDOMComponentWithClass(instance, testCase.className));
});
});
});
24 changes: 24 additions & 0 deletions test/InputSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,30 @@ describe('Input', function () {
assert.ok(ReactTestUtils.findRenderedDOMComponentWithClass(instance, 'help-block'));
});

it('renders form-group class', function() {
let instance = ReactTestUtils.renderIntoDocument(
<Input />
);

assert.ok(ReactTestUtils.findRenderedDOMComponentWithClass(instance, 'form-group'));
});

it('renders no form-group class', function() {
let instance = ReactTestUtils.renderIntoDocument(
<Input standalone />
);

assert.equal(ReactTestUtils.scryRenderedDOMComponentsWithClass(instance, 'form-group').length, 0);
});

it('renders custom-form-group class', function() {
let instance = ReactTestUtils.renderIntoDocument(
<Input groupClassName='custom-form-class' />
);

assert.ok(ReactTestUtils.findRenderedDOMComponentWithClass(instance, 'custom-form-class'));
});

it('renders feedback icon', function () {
let instance = ReactTestUtils.renderIntoDocument(
<Input hasFeedback={true} bsStyle="error" />
Expand Down

0 comments on commit bfb3e6c

Please sign in to comment.