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

propagate options changes to consumer #18

Merged
merged 1 commit into from
Mar 29, 2019
Merged
Show file tree
Hide file tree
Changes from all 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
37 changes: 0 additions & 37 deletions src-docs/src/views/selectable/data.js

This file was deleted.

18 changes: 7 additions & 11 deletions src-docs/src/views/selectable/selectable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,28 @@ import { EuiSelectable } from '../../../../src/components/selectable';
import { Option } from '../../../../src/components/selectable/types';
import { Options } from './data';

export default class extends Component<{}, { selectedOptions: Option[] }> {
options: Option[] = [];
export default class extends Component<{}, { options: Option[] }> {
constructor(props: any) {
super(props);

this.options = Options as Option[];
const selectedOptions = this.options.filter(option => option.checked);

this.state = {
selectedOptions,
options: Options as Option[],
};
}

onChange = (selectedOptions: Option[]) => {
onChange = (options: Option[]) => {
this.setState({
selectedOptions,
options,
});
};

render() {
const { selectedOptions } = this.state;
const { options } = this.state;

return (
<EuiSelectable
options={this.options}
onChange={() => this.onChange(selectedOptions)}
options={options}
onChange={this.onChange}
listProps={{ bordered: true }}>
{list => list}
</EuiSelectable>
Expand Down
2 changes: 1 addition & 1 deletion src-docs/src/views/selectable/selectable_custom_render.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export default class extends Component {
<EuiSelectable
searchable
options={options}
onChange={() => this.onChange(options)}
onChange={this.onChange}
{...customProps}
>
{(list, search) => (
Expand Down
40 changes: 39 additions & 1 deletion src-docs/src/views/selectable/selectable_example.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import { Link } from 'react-router';
import { Fragment } from 'react-is';

import { renderToHtml } from '../../services';

Expand All @@ -23,10 +24,13 @@ const selectablePopoverSource = require('!!raw-loader!./selectable_popover');
const selectablePopoverHtml = renderToHtml(SelectablePopover);

import SelectableSearch from './selectable_search';
import { Fragment } from 'react-is';
const selectableSearchSource = require('!!raw-loader!./selectable_search');
const selectableSearchHtml = renderToHtml(SelectableSearch);

import SelectableSingle from './selectable_single';
const selectableSingleSource = require('!!raw-loader!./selectable_single');
const selectableSingleHtml = renderToHtml(SelectableSingle);

import SelectableExclusion from './selectable_exclusion';
const selectableExclusionSource = require('!!raw-loader!./selectable_exclusion');
const selectableExclusionHtml = renderToHtml(SelectableExclusion);
Expand Down Expand Up @@ -168,6 +172,40 @@ export const SelectableExample = {
</Fragment>
)}
</EuiSelectable>`,
},
{
title: 'Single Selection',
source: [
{
type: GuideSectionTypes.JS,
code: selectableSingleSource,
},
{
type: GuideSectionTypes.HTML,
code: selectableSingleHtml,
},
],
text: (
<Fragment>
<p>
Selection can be restricted to a single option at a time with the <EuiCode>singleSelection</EuiCode> prop.
Passing <EuiCode>true</EuiCode> allows for 0 or 1 option to be selected, while
<EuiCode>`always`</EuiCode> requires 1 option to be selected at all times.
The default value is <EuiCode>false</EuiCode>.
</p>
</Fragment>
),
props: { EuiSelectable },
demo: <SelectableSingle />,
snippet: `
<EuiSelectable
options={options}
onChange={this.onChange}
singleSelection={true}
listProps={{ bordered: true }}>
{list => list}
</EuiSelectable>
`,
},
{
title: 'Sizing and containers',
Expand Down
9 changes: 2 additions & 7 deletions src-docs/src/views/selectable/selectable_exclusion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,11 @@ import { Option } from '../../../../src/components/selectable/types';
import { Options } from './data';

export default class extends Component<{}, { options: Option[] }> {
options: Option[] = [];
constructor(props: any) {
super(props);

this.options = Options as Option[];
this.state = {
options: this.options,
options: Options as Option[],
};
}

Expand All @@ -25,10 +23,7 @@ export default class extends Component<{}, { options: Option[] }> {
const { options } = this.state;

return (
<EuiSelectable
allowExclusions
options={options}
onChange={() => this.onChange(options)}>
<EuiSelectable allowExclusions options={options} onChange={this.onChange}>
{list => list}
</EuiSelectable>
);
Expand Down
3 changes: 1 addition & 2 deletions src-docs/src/views/selectable/selectable_search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { Option } from '../../../../src/components/selectable/types';
import { Options } from './data';

export default class extends Component<{}, { options: Option[] }> {
options: Option[] = [];
constructor(props: any) {
super(props);

Expand All @@ -30,7 +29,7 @@ export default class extends Component<{}, { options: Option[] }> {
'data-test-subj': 'selectableSearchHere',
}}
options={options}
onChange={() => this.onChange(options)}>
onChange={this.onChange}>
{(list, search) => (
<Fragment>
{search}
Expand Down
38 changes: 38 additions & 0 deletions src-docs/src/views/selectable/selectable_single.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React, { Component } from 'react';

import { EuiSelectable } from '../../../../src/components/selectable';
import { Option } from '../../../../src/components/selectable/types';
import { Options } from './data';

export default class extends Component<{}, { options: Option[] }> {
constructor(props: any) {
super(props);

this.state = {
options: Options.map(option => {
const { checked, ...checklessOption } = option;
return { ...checklessOption };
}) as Option[],
};
}

onChange = (options: Option[]) => {
this.setState({
options,
});
};

render() {
const { options } = this.state;

return (
<EuiSelectable
options={options}
onChange={this.onChange}
singleSelection={true}
listProps={{ bordered: true }}>
{list => list}
</EuiSelectable>
);
}
}
7 changes: 4 additions & 3 deletions src/components/selectable/selectable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ type EuiSelectableOptionsListPropsWithDefaults = RequiredEuiSelectableOptionsLis

export type EuiSelectableProps = Omit<
HTMLAttributes<HTMLDivElement>,
'children'
'children' | 'onChange'
> &
CommonProps & {
/**
Expand Down Expand Up @@ -240,9 +240,10 @@ export class EuiSelectable extends Component<
};

onOptionClick = (options: Option[]) => {
this.setState({
this.setState(state => ({
options,
});
visibleOptions: getMatchingOptions(options, state.searchValue),
}));
if (this.props.onChange) {
this.props.onChange(options);
}
Expand Down
51 changes: 41 additions & 10 deletions src/components/selectable/selectable_list/selectable_list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -225,24 +225,55 @@ export class EuiSelectableList extends Component<EuiSelectableListProps> {

private onAddOption = (addedOption: Option) => {
const { onOptionClick, options, singleSelection } = this.props;
if (singleSelection) {
options.map(option => delete option.checked);
}
addedOption.checked = 'on';
onOptionClick(options);

const updatedOptions = options.map(option => {
// if singleSelection is enabled, uncheck any selected option(s)
const updatedOption = { ...option };
if (singleSelection) {
delete updatedOption.checked;
}

// if this is the now-selected option, check it
if (option === addedOption) {
updatedOption.checked = 'on';
}

return updatedOption;
});

onOptionClick(updatedOptions);
};

private onRemoveOption = (removedOption: Option) => {
const { onOptionClick, singleSelection, options } = this.props;
if (singleSelection !== 'always') {
delete removedOption.checked;
}
onOptionClick(options);

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

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

return updatedOption;
});

onOptionClick(updatedOptions);
};

private onExcludeOption = (excludedOption: Option) => {
const { onOptionClick, options } = this.props;
excludedOption.checked = 'off';
onOptionClick(options);

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

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

return updatedOption;
});

onOptionClick(updatedOptions);
};
}