Skip to content

Commit 866ec5b

Browse files
authored
fix(Form): fix controlId override behavior on FormRange and FormSelect (react-bootstrap#5880)
1 parent a307102 commit 866ec5b

File tree

4 files changed

+53
-1
lines changed

4 files changed

+53
-1
lines changed

src/FormRange.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import classNames from 'classnames';
22
import PropTypes from 'prop-types';
33
import * as React from 'react';
4+
import { useContext } from 'react';
45
import { useBootstrapPrefix } from './ThemeProvider';
56
import { BsPrefixOnlyProps } from './helpers';
7+
import FormContext from './FormContext';
68

79
export interface FormRangeProps
810
extends BsPrefixOnlyProps,
@@ -30,10 +32,16 @@ const propTypes = {
3032

3133
/** A callback fired when the `value` prop changes */
3234
onChange: PropTypes.func,
35+
36+
/**
37+
* Uses `controlId` from `<FormGroup>` if not explicitly specified.
38+
*/
39+
id: PropTypes.string,
3340
};
3441

3542
const FormRange = React.forwardRef<HTMLInputElement, FormRangeProps>(
36-
({ bsPrefix, className, ...props }, ref) => {
43+
({ bsPrefix, className, id, ...props }, ref) => {
44+
const { controlId } = useContext(FormContext);
3745
bsPrefix = useBootstrapPrefix(bsPrefix, 'form-range');
3846

3947
return (
@@ -42,6 +50,7 @@ const FormRange = React.forwardRef<HTMLInputElement, FormRangeProps>(
4250
type="range"
4351
ref={ref}
4452
className={classNames(className, bsPrefix)}
53+
id={id || controlId}
4554
/>
4655
);
4756
},

src/FormSelect.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import classNames from 'classnames';
22
import PropTypes from 'prop-types';
33
import * as React from 'react';
4+
import { useContext } from 'react';
45
import { useBootstrapPrefix } from './ThemeProvider';
56
import { BsPrefixOnlyProps, BsPrefixRefForwardingComponent } from './helpers';
7+
import FormContext from './FormContext';
68

79
export interface FormSelectProps
810
extends BsPrefixOnlyProps,
@@ -66,10 +68,12 @@ const FormSelect: BsPrefixRefForwardingComponent<'select', FormSelectProps> =
6668
className,
6769
isValid = false,
6870
isInvalid = false,
71+
id,
6972
...props
7073
},
7174
ref,
7275
) => {
76+
const { controlId } = useContext(FormContext);
7377
bsPrefix = useBootstrapPrefix(bsPrefix, 'form-select');
7478

7579
return (
@@ -84,6 +88,7 @@ const FormSelect: BsPrefixRefForwardingComponent<'select', FormSelectProps> =
8488
isValid && `is-valid`,
8589
isInvalid && `is-invalid`,
8690
)}
91+
id={id || controlId}
8792
/>
8893
);
8994
},

test/FormRangeSpec.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,28 @@
11
import { mount } from 'enzyme';
22

33
import FormRange from '../src/FormRange';
4+
import FormGroup from '../src/FormGroup';
45

56
describe('<FormRange>', () => {
67
it('should render correctly', () => {
78
mount(
89
<FormRange id="foo" name="bar" className="my-control" />,
910
).assertSingle('input#foo.form-range.my-control[type="range"][name="bar"]');
1011
});
12+
13+
it('should render controlId as id correctly', () => {
14+
mount(
15+
<FormGroup controlId="test-id">
16+
<FormRange />
17+
</FormGroup>,
18+
).assertSingle('.form-range#test-id');
19+
});
20+
21+
it('should override controlId correctly', () => {
22+
mount(
23+
<FormGroup controlId="test-id">
24+
<FormRange id="overridden-id" />
25+
</FormGroup>,
26+
).assertSingle('.form-range#overridden-id:not(#test-id)');
27+
});
1128
});

test/FormSelectSpec.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { mount } from 'enzyme';
22

33
import FormSelect from '../src/FormSelect';
4+
import FormGroup from '../src/FormGroup';
45

56
describe('<FormSelect>', () => {
67
it('should render correctly', () => {
@@ -30,4 +31,24 @@ describe('<FormSelect>', () => {
3031
'select.form-select.is-invalid',
3132
);
3233
});
34+
35+
it('should render controlId correctly', () => {
36+
mount(
37+
<FormGroup controlId="test-id">
38+
<FormSelect>
39+
<option>1</option>
40+
</FormSelect>
41+
</FormGroup>,
42+
).assertSingle('.form-select#test-id');
43+
});
44+
45+
it('should override controlId correctly', () => {
46+
mount(
47+
<FormGroup controlId="test-id">
48+
<FormSelect id="overridden-id">
49+
<option>1</option>
50+
</FormSelect>
51+
</FormGroup>,
52+
).assertSingle('.form-select#overridden-id:not(#test-id)');
53+
});
3354
});

0 commit comments

Comments
 (0)