Skip to content

Commit

Permalink
[EuiSelectable] Add the single triggering option as a parameter to `o…
Browse files Browse the repository at this point in the history
…nChange` (#6487)

* [EuiSelectable] Add the single triggering option as a parameter to `onChange`

* [REVERT ME] Docs example

* changelog

* Revert "[REVERT ME] Docs example"

This reverts commit 7346ee4.
  • Loading branch information
Cee authored Dec 15, 2022
1 parent 4edc93a commit 784a553
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 11 deletions.
10 changes: 9 additions & 1 deletion src/components/selectable/selectable.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ describe('EuiSelectable', () => {
});

describe('onChange', () => {
it('calls onChange with selected options array and click/keyboard event', () => {
it('calls onChange with selected options array, click/keyboard event, and the clicked option', () => {
const onChange = jest.fn();
const component = mount(
<EuiSelectable options={options} onChange={onChange}>
Expand All @@ -388,11 +388,19 @@ describe('EuiSelectable', () => {
expect(onChange).toHaveBeenCalledTimes(1);
expect(onChange.mock.calls[0][0][0].checked).toEqual('on');
expect(onChange.mock.calls[0][1].type).toEqual('click');
expect(onChange.mock.calls[0][2]).toEqual({
...options[0],
checked: 'on',
});

component.simulate('keydown', { key: 'Enter', shiftKey: true });
expect(onChange).toHaveBeenCalledTimes(2);
expect(onChange.mock.calls[1][0][0].checked).toEqual('on');
expect(onChange.mock.calls[1][1].type).toEqual('keydown');
expect(onChange.mock.calls[1][2]).toEqual({
...options[0],
checked: 'on',
});
});
});

Expand Down
11 changes: 7 additions & 4 deletions src/components/selectable/selectable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,13 @@ export type EuiSelectableProps<T = {}> = CommonProps &
options: Array<EuiSelectableOption<T>>;
/**
* Passes back the altered `options` array with selected options having `checked: 'on'`.
* Also passes back the React click/keyboard event as a second argument.
* Also passes back the React click/keyboard event as a second argument,
* and the option that triggered the onChange event as a third argument.
*/
onChange?: (
options: Array<EuiSelectableOption<T>>,
event: EuiSelectableOnChangeEvent
event: EuiSelectableOnChangeEvent,
changedOption: EuiSelectableOption<T>
) => void;
/**
* Passes back the current active option whenever the user changes the currently
Expand Down Expand Up @@ -455,7 +457,8 @@ export class EuiSelectable<T = {}> extends Component<

onOptionClick = (
options: Array<EuiSelectableOption<T>>,
event: EuiSelectableOnChangeEvent
event: EuiSelectableOnChangeEvent,
clickedOption: EuiSelectableOption<T>
) => {
const { isPreFiltered, onChange } = this.props;
const { searchValue } = this.state;
Expand All @@ -468,7 +471,7 @@ export class EuiSelectable<T = {}> extends Component<
this.setState({ visibleOptions });

if (onChange) {
onChange(options, event);
onChange(options, event, clickedOption);
}
};

Expand Down
19 changes: 13 additions & 6 deletions src/components/selectable/selectable_list/selectable_list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,13 @@ export type EuiSelectableListProps<T> = EuiSelectableOptionsListProps & {
*/
searchValue: string;
/**
* Returns the array of options with altered checked state
* Returns the array of options with altered checked state, the click/keyboard event,
* and the option that triggered the click/keyboard event
*/
onOptionClick: (
options: Array<EuiSelectableOption<T>>,
event: EuiSelectableOnChangeEvent
event: EuiSelectableOnChangeEvent,
clickedOption: EuiSelectableOption<T>
) => void;
/**
* Custom render for the label portion of the option;
Expand Down Expand Up @@ -450,6 +452,7 @@ export class EuiSelectableList<T> extends Component<EuiSelectableListProps<T>> {
event: EuiSelectableOnChangeEvent
) => {
const { onOptionClick, options, singleSelection } = this.props;
let changedOption = { ...addedOption };

const updatedOptions = options.map((option) => {
// if singleSelection is enabled, uncheck any selected option(s)
Expand All @@ -461,50 +464,54 @@ export class EuiSelectableList<T> extends Component<EuiSelectableListProps<T>> {
// if this is the now-selected option, check it
if (option === addedOption) {
updatedOption.checked = 'on';
changedOption = updatedOption;
}

return updatedOption;
});

onOptionClick(updatedOptions, event);
onOptionClick(updatedOptions, event, changedOption);
};

private onRemoveOption = (
removedOption: EuiSelectableOption<T>,
event: EuiSelectableOnChangeEvent
) => {
const { onOptionClick, singleSelection, options } = this.props;
let changedOption = { ...removedOption };

const updatedOptions = options.map((option) => {
const updatedOption = { ...option };

if (option === removedOption && singleSelection !== 'always') {
delete updatedOption.checked;
changedOption = updatedOption;
}

return updatedOption;
});

onOptionClick(updatedOptions, event);
onOptionClick(updatedOptions, event, changedOption);
};

private onExcludeOption = (
excludedOption: EuiSelectableOption<T>,
event: EuiSelectableOnChangeEvent
) => {
const { onOptionClick, options } = this.props;
excludedOption.checked = 'off';
let changedOption = { ...excludedOption };

const updatedOptions = options.map((option) => {
const updatedOption = { ...option };

if (option === excludedOption) {
updatedOption.checked = 'off';
changedOption = updatedOption;
}

return updatedOption;
});

onOptionClick(updatedOptions, event);
onOptionClick(updatedOptions, event, changedOption);
};
}
1 change: 1 addition & 0 deletions upcoming_changelogs/6487.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Added a third argument to `EuiSelectable`'s `onChange` callback. The single `option` object that triggered the `onChange` event is now also passed to consumers with its most recent `checked` state

0 comments on commit 784a553

Please sign in to comment.