Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
feat(CustomerInput): added htmlFor prop (#1417)
* Added htmlFor prop for CustomInput
* Added proptype, examples
  • Loading branch information
Dakkers authored and TheSharpieOne committed Mar 4, 2019
1 parent 90cbbd0 commit a590880
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 2 deletions.
3 changes: 3 additions & 0 deletions docs/lib/examples/CustomControls.js
Expand Up @@ -11,6 +11,7 @@ export default class Example extends React.Component {
<CustomInput type="checkbox" id="exampleCustomCheckbox" label="Check this custom checkbox" />
<CustomInput type="checkbox" id="exampleCustomCheckbox2" label="Or this one" />
<CustomInput type="checkbox" id="exampleCustomCheckbox3" label="But not this disabled one" disabled />
<CustomInput type="checkbox" id="exampleCustomCheckbox4" label="Can't click this label to check!" htmlFor="exampleCustomCheckbox4_X" disabled />
</div>
</FormGroup>
<FormGroup>
Expand All @@ -19,6 +20,7 @@ export default class Example extends React.Component {
<CustomInput type="radio" id="exampleCustomRadio" name="customRadio" label="Select this custom radio" />
<CustomInput type="radio" id="exampleCustomRadio2" name="customRadio" label="Or this one" />
<CustomInput type="radio" id="exampleCustomRadio3" label="But not this disabled one" disabled />
<CustomInput type="radio" id="exampleCustomRadio4" label="Can't click this label to select!" htmlFor="exampleCustomRadio4_X" disabled />
</div>
</FormGroup>
<FormGroup>
Expand All @@ -27,6 +29,7 @@ export default class Example extends React.Component {
<CustomInput type="switch" id="exampleCustomSwitch" name="customSwitch" label="Turn on this custom switch" />
<CustomInput type="switch" id="exampleCustomSwitch2" name="customSwitch" label="Or this one" />
<CustomInput type="switch" id="exampleCustomSwitch3" label="But not this disabled one" disabled />
<CustomInput type="switch" id="exampleCustomSwitch4" label="Can't click this label to turn on!" htmlFor="exampleCustomSwitch4_X" disabled />
</div>
</FormGroup>
<FormGroup>
Expand Down
8 changes: 6 additions & 2 deletions src/CustomInput.js
Expand Up @@ -12,6 +12,7 @@ const propTypes = {
valid: PropTypes.bool,
invalid: PropTypes.bool,
bsSize: PropTypes.string,
htmlFor: PropTypes.string,
cssModule: PropTypes.object,
children: PropTypes.oneOfType([PropTypes.node, PropTypes.array, PropTypes.func]),
innerRef: PropTypes.oneOfType([
Expand All @@ -32,6 +33,7 @@ function CustomInput(props) {
children,
bsSize,
innerRef,
htmlFor,
...attributes
} = props;

Expand All @@ -48,6 +50,8 @@ function CustomInput(props) {
valid && 'is-valid',
), cssModule);

const labelHtmlFor = htmlFor || attributes.id;

if (type === 'select') {
return <select {...attributes} ref={innerRef} className={classNames(validationClassNames, customClass)}>{children}</select>;
}
Expand All @@ -56,7 +60,7 @@ function CustomInput(props) {
return (
<div className={customClass}>
<input {...attributes} ref={innerRef} className={classNames(validationClassNames, mapToCssModules('custom-file-input', cssModule))} />
<label className={mapToCssModules('custom-file-label', cssModule)} htmlFor={attributes.id}>{label || 'Choose file'}</label>
<label className={mapToCssModules('custom-file-label', cssModule)} htmlFor={labelHtmlFor}>{label || 'Choose file'}</label>
</div>
);
}
Expand All @@ -81,7 +85,7 @@ function CustomInput(props) {
ref={innerRef}
className={classNames(validationClassNames, mapToCssModules('custom-control-input', cssModule))}
/>
<label className={mapToCssModules('custom-control-label', cssModule)} htmlFor={attributes.id}>{label}</label>
<label className={mapToCssModules('custom-control-label', cssModule)} htmlFor={labelHtmlFor}>{label}</label>
{children}
</div>
);
Expand Down
24 changes: 24 additions & 0 deletions src/__tests__/CustomInput.spec.js
Expand Up @@ -25,6 +25,12 @@ describe('Custom Inputs', () => {
expect(checkbox.find('label').prop('htmlFor')).toBe('yo');
});

it('should pass id to both the input and label nodes, with an overriden for on the label node', () => {
const checkbox = mount(<CustomInput type="checkbox" htmlFor="custom-for" id="yo" />);
expect(checkbox.find('input').prop('id')).toBe('yo');
expect(checkbox.find('label').prop('htmlFor')).toBe('custom-for');
});

it('should pass classNames to the outer div', () => {
const checkbox = mount(<CustomInput type="checkbox" className="yo" />);
expect(checkbox.find('.custom-control').prop('className').indexOf('yo') > -1).toBeTruthy();
Expand Down Expand Up @@ -85,6 +91,12 @@ describe('Custom Inputs', () => {
expect(radio.find('label').prop('htmlFor')).toBe('yo');
});

it('should pass id to both the input and label nodes, with an overriden for on the label node', () => {
const radio = mount(<CustomInput type="radio" htmlFor="custom-for" id="yo" />);
expect(radio.find('input').prop('id')).toBe('yo');
expect(radio.find('label').prop('htmlFor')).toBe('custom-for');
});

it('should pass classNames to the outer div', () => {
const radio = mount(<CustomInput type="radio" className="yo" />);
expect(radio.find('.custom-control').prop('className').indexOf('yo') > -1).toBeTruthy();
Expand Down Expand Up @@ -125,6 +137,12 @@ describe('Custom Inputs', () => {
expect(checkbox.find('label').prop('htmlFor')).toBe('yo');
});

it('should pass id to both the input and label nodes, with an overriden for on the label node', () => {
const checkbox = mount(<CustomInput type="switch" htmlFor="custom-for" id="yo" />);
expect(checkbox.find('input').prop('id')).toBe('yo');
expect(checkbox.find('label').prop('htmlFor')).toBe('custom-for');
});

it('should pass classNames to the outer div', () => {
const checkbox = mount(<CustomInput type="switch" className="yo" />);
expect(checkbox.find('.custom-control').prop('className').indexOf('yo') > -1).toBeTruthy();
Expand Down Expand Up @@ -219,6 +237,12 @@ describe('Custom Inputs', () => {
expect(file.find('label').prop('htmlFor')).toBe('yo');
});

it('should pass id to both the input and label nodes, with an overriden for on the label node', () => {
const file = mount(<CustomInput type="file" htmlFor="custom-for" id="yo" />);
expect(file.find('input').prop('id')).toBe('yo');
expect(file.find('label').prop('htmlFor')).toBe('custom-for');
});

it('should pass classNames to the outer div', () => {
const file = mount(<CustomInput type="file" className="yo" />);
expect(file.find('.custom-file').prop('className').indexOf('yo') > -1).toBeTruthy();
Expand Down

0 comments on commit a590880

Please sign in to comment.