Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow specification of group's input props #571

Merged
merged 6 commits into from
Jul 4, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ Clicking an unselected checkbox adds its value to this array, and clicking a sel
* `input` **[Object][145]** A `redux-form` [input][146] object
* `meta` **[Object][145]** A `redux-form` [meta][147] object
* `options` **[Array][143]** An array of checkbox values (strings, numbers, or key-value pairs)
* `checkboxInputProps` **[Object][145]** An object of key-value pairs representing props to pass down to all checkbox inputs (optional, default `{}`)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you give an example of what the key/value pairs look like, either here or in the example below. I think an example with the className key would be most useful.


### Examples

Expand Down Expand Up @@ -762,6 +763,7 @@ The value of the entire `RadioGroup` component is the value of the currently sel
* `input` **[Object][145]** A `redux-form` [input][146] object
* `meta` **[Object][145]** A `redux-form` [meta][147] object
* `options` **[Array][143]** An array of radio button values (strings, numbers, booleans, or key-value pairs)
* `radioInputProps` **[Object][145]** An object of key-value pairs representing props to pass down to all radio inputs (optional, default `{}`)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same "example" request here.


### Examples

Expand Down
3 changes: 3 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
module.exports = {
'setupFiles': [
'./test/setup.js',
],
"watchPathIgnorePatterns": [
"<rootDir>/node_modules",
]
}
31 changes: 31 additions & 0 deletions migration-guides/v7.0.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ This version contains the following breaking changes:
15. `<Modal />` no longer overwrites the default modal or overlay class
16. `<Modal />` targets #root instead of the body
17. `<DateInput />`s dependency on react-datepicker was upgraded from v1 to v4
18. `<RadioGroup />` and `<CheckboxGroup />` components no longer pass className prop to inputs

The required changes for each item are detailed below.

Expand Down Expand Up @@ -395,3 +396,33 @@ This introduces the following breaking changes:
More details: https://github.com/Hacker0x01/react-datepicker/releases.

Of these breaking changes, the deprecation of `moment` has the highest likelihood of affecting your application. This will only impact your application if you referenced the `moment` library elsewhere in the codebase **without** installing the package directly as a dependency.

## 18. `<RadioGroup />` and `<CheckboxGroup />` components no longer pass className prop to inputs
This change might affect the styles in your application. If you are passing in the `className` prop and your styles rely on targeting both the outer-most fieldset _and_ the inputs, you can either update your scss or you can pass in the same class name via `<type>InputProps`.

### Before
```jsx
<RadioGroup className="custom-radio-group" />
```

```scss
.custom-radio-group {
margin-bottom: 2px;
}
```
### After
```scss
.custom-radio-group {
margin-bottom: 2px;
input {
margin-bottom: 2px;
}
}
```
Or,
```jsx
<RadioGroup
className="custom-radio-group"
radioInputProps={{ className: 'custom-radio-group' }}
/>
```
17 changes: 13 additions & 4 deletions src/forms/inputs/checkbox-group.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react'
import PropTypes from 'prop-types'
import Checkbox from './checkbox'
import {
checkboxGroupPropTypes,
Expand Down Expand Up @@ -27,6 +28,7 @@ import { addToArray, removeFromArray, serializeOptions, compose } from '../../ut
* @param {Object} input - A `redux-form` [input](http://redux-form.com/6.5.0/docs/api/Field.md/#input-props) object
* @param {Object} meta - A `redux-form` [meta](http://redux-form.com/6.5.0/docs/api/Field.md/#meta-props) object
* @param {Array} options - An array of checkbox values (strings, numbers, or key-value pairs)
* @param {Object} [checkboxInputProps={}] - An object of key-value pairs representing props to pass down to all checkbox inputs
* @example
*
* function TodoForm ({ handleSubmit, pristine, invalid, submitting }) {
Expand All @@ -53,11 +55,15 @@ import { addToArray, removeFromArray, serializeOptions, compose } from '../../ut

const propTypes = {
...checkboxGroupPropTypes,
className: PropTypes.string,
checkboxInputProps: PropTypes.object,
options: fieldOptionsType
}

const defaultProps = {
options: []
className: 'CheckboxGroup',
checkboxInputProps: {},
options: [],
}

function CheckboxGroupLegend ({ name, label }) {
Expand All @@ -71,6 +77,8 @@ function CheckboxGroup (props) {
input: { value, onChange, name },
meta, // eslint-disable-line no-unused-vars
options,
className,
checkboxInputProps,
...rest
} = omitLabelProps(props)
const optionObjects = serializeOptions(options)
Expand All @@ -84,8 +92,8 @@ function CheckboxGroup (props) {
}
return (
<LabeledField
className="CheckboxGroup"
labelComponent={ CheckboxGroupLegend }
className={className}
labelComponent={CheckboxGroupLegend}
{ ...props }
>
{
Expand All @@ -101,7 +109,8 @@ function CheckboxGroup (props) {
},
meta: {},
label: option.key,
...rest
...rest,
...checkboxInputProps,
}}
/>
)
Expand Down
18 changes: 13 additions & 5 deletions src/forms/inputs/radio-group.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react'
// import PropTypes from 'prop-types'
import PropTypes from 'prop-types'
import {
convertNameToLabel,
radioGroupPropTypes,
Expand All @@ -26,6 +26,7 @@ import { serializeOptions, filterInvalidDOMProps } from '../../utils'
* @param {Object} input - A `redux-form` [input](http://redux-form.com/6.5.0/docs/api/Field.md/#input-props) object
* @param {Object} meta - A `redux-form` [meta](http://redux-form.com/6.5.0/docs/api/Field.md/#meta-props) object
* @param {Array} options - An array of radio button values (strings, numbers, booleans, or key-value pairs)
* @param {Object} [radioInputProps={}] - An object of key-value pairs representing props to pass down to all radio inputs
* @example
*
* function FavoriteFoodForm ({ handleSubmit, pristine, invalid, submitting }) {
Expand All @@ -52,11 +53,15 @@ import { serializeOptions, filterInvalidDOMProps } from '../../utils'

const propTypes = {
...radioGroupPropTypes,
options: fieldOptionsType
className: PropTypes.string,
options: fieldOptionsType,
radioInputProps: PropTypes.object,
}

const defaultProps = {
options: []
options: [],
className: 'RadioGroup',
radioInputProps: {},
}

function RadioGroupLegend ({ label, name }) {
Expand Down Expand Up @@ -98,12 +103,14 @@ function RadioGroup (props) {
input: { value, onChange, name },
meta, // eslint-disable-line no-unused-vars
options,
className,
radioInputProps,
...rest
} = omitLabelProps(props)
const optionObjects = serializeOptions(options)
return (
<LabeledField
className="RadioGroup"
className={className}
labelComponent={ RadioGroupLegend }
{ ...props }
>
Expand All @@ -123,7 +130,8 @@ function RadioGroup (props) {
meta: {},
checked: value === option.value,
label: option.key,
...rest
...rest,
...radioInputProps,
}}
/>
)
Expand Down
16 changes: 16 additions & 0 deletions stories/forms/inputs/checkbox-group.story.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ const options = [
{ key: 'Third Option', value: '3' }
]

const SpecialLabel = ({ id, label }) => (
<span>
<label htmlFor={id}><em>{label}</em></label>
</span>
)

storiesOf('CheckboxGroup', module)
.add('with default label', () => (
<CheckboxGroup
Expand Down Expand Up @@ -64,3 +70,13 @@ storiesOf('CheckboxGroup', module)
meta={{}}
/>
))
.add('with input props specified', () => (
<CheckboxGroup
input={inputProps}
meta={{}}
options={options}
checkboxInputProps={{
labelComponent: SpecialLabel
}}
/>
))
16 changes: 16 additions & 0 deletions stories/forms/inputs/radio-group.story.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ const options = [
{ key: 'Third Option', value: '3' }
]

const SpecialLabel = ({ id, label }) => (
<span>
<label htmlFor={id}><em>{label}</em></label>
</span>
)

storiesOf('RadioGroup', module)
.add('with default label', () => (
<RadioGroup
Expand Down Expand Up @@ -79,4 +85,14 @@ storiesOf('RadioGroup', module)
meta={{}}
options={[{ key: 'Yes', value: true }, { key: 'No', value: false }]}
/>
))
.add('with input props specified', () => (
<RadioGroup
input={inputProps}
meta={{}}
options={options}
radioInputProps={{
labelComponent: SpecialLabel
}}
/>
))
32 changes: 32 additions & 0 deletions test/forms/inputs/checkbox-group.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,35 @@ test('CheckboxGroup has a legend with the group\'s label (when provided)', () =>
expect(legend).toBeTruthy()
expect(legend.text()).toEqual('Checkbox Group')
})

test('CheckboxGroup does not pass class to children', () => {
const props = {
input: {
name: 'testGroup',
value: '',
},
meta: {},
options: ['TOGGLED_OPTION'],
className:'custom-class'
}
const wrapper = mount(<CheckboxGroup { ...props }/>)
expect(wrapper.find('.custom-class').hostNodes().length).toBe(1)
})

test('CheckboxGroup passes down props to children', () => {
const props = {
input: {
name: 'testGroup',
value: '',
},
meta: {},
options: ['TOGGLED_OPTION'],
className:'custom-group-class',
checkboxInputProps: {
className: 'custom-input-class',
}
}
const wrapper = mount(<CheckboxGroup { ...props }/>)
expect(wrapper.find('input.custom-group-class').exists()).toBe(false)
expect(wrapper.find('input.custom-input-class').exists()).toBe(true)
})
41 changes: 37 additions & 4 deletions test/forms/inputs/radio-group.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ test('RadioGroup changes value when buttons are clicked', () => {
expect(onChange).toHaveBeenCalledWith('Option 2')
})

test('A RadioGroup\'s inputs all have the same name', () => {
test('RadioGroup\'s inputs all have the same name', () => {
const name = "sameName"
const props = {
input: {
Expand All @@ -35,7 +35,7 @@ test('A RadioGroup\'s inputs all have the same name', () => {
expect(wrapper.find('input').last().prop('name')).toEqual(name)
})

test('A RadioGroup input has a value that matches the corresponding option\'s value', () => {
test('RadioGroup input has a value that matches the corresponding option\'s value', () => {
const props = {
input: {
name: 'test',
Expand All @@ -49,7 +49,7 @@ test('A RadioGroup input has a value that matches the corresponding option\'s va
expect(wrapper.find('input').last().prop('value')).toEqual('Option 2')
})

test('A RadioGroup has a legend with the group\'s name by default', () => {
test('RadioGroup has a legend with the group\'s name by default', () => {
const name = "sameName"
const props = {
input: {
Expand All @@ -65,7 +65,7 @@ test('A RadioGroup has a legend with the group\'s name by default', () => {
expect(legend.text()).toEqual('Same Name')
})

test('A RadioGroup has a legend with the group\'s label (when provided)', () => {
test('RadioGroup has a legend with the group\'s label (when provided)', () => {
const name = "sameName"
const props = {
input: {
Expand All @@ -82,3 +82,36 @@ test('A RadioGroup has a legend with the group\'s label (when provided)', () =>
expect(legend.text()).toEqual('Different Name')
})

test('RadioGroup does not pass down class name', () => {
const onChange = jest.fn()
const props = {
input: {
name: 'test',
value: '',
onChange,
},
meta: {},
options: ['Option 1', 'Option 2'],
className: 'custom-radio'
}
const wrapper = mount(<RadioGroup { ...props }/>)
expect(wrapper.find('.custom-radio').hostNodes().length).toEqual(1)
})

test('RadioGroup passes down props to children', () => {
const onChange = jest.fn()
const props = {
input: {
name: 'test',
value: '',
onChange,
},
meta: {},
options: ['Option 1', 'Option 2'],
className: 'custom-radio-group',
radioInputProps: { className: 'custom-radio-input' },
}
const wrapper = mount(<RadioGroup { ...props }/>)
expect(wrapper.find('input.custom-radio-group').exists()).toBe(false)
expect(wrapper.find('input.custom-radio-input').exists()).toBe(true)
})