Skip to content

Commit

Permalink
Support disallowing custom options.
Browse files Browse the repository at this point in the history
  • Loading branch information
cjcenizal committed Mar 27, 2018
1 parent 8a3d3e2 commit 1d34369
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const <%= componentExampleName %>Example = {
Description needed: how to use the <EuiCode>Eui<%= componentExampleName %></EuiCode> component.
</p>
),
components: { <%= componentName %> },
props: { <%= componentName %> },
demo: <<%= componentExampleName %> />,
}],
};
24 changes: 22 additions & 2 deletions src-docs/src/views/combo_box/combo_box_example.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ import Groups from './groups';
const groupsSource = require('!!raw-loader!./groups');
const groupsHtml = renderToHtml(Groups);

import DisallowCustomOptions from './disallow_custom_options';
const disallowCustomOptionsSource = require('!!raw-loader!./disallow_custom_options');
const disallowCustomOptionsHtml = renderToHtml(DisallowCustomOptions);

export const ComboBoxExample = {
title: 'Combo Box',
sections: [{
Expand All @@ -37,7 +41,7 @@ export const ComboBoxExample = {
a custom value in addition to selecting from a predetermined list.
</p>
),
components: { EuiComboBox },
props: { EuiComboBox },
demo: <ComboBox />,
}, {
title: 'Groups',
Expand All @@ -53,7 +57,23 @@ export const ComboBoxExample = {
You can group options together. The groups <em>won&rsquo;t</em> match against the search value.
</p>
),
components: { EuiComboBox },
props: { EuiComboBox },
demo: <Groups />,
}, {
title: 'Disallowing custom options',
source: [{
type: GuideSectionTypes.JS,
code: disallowCustomOptionsSource,
}, {
type: GuideSectionTypes.HTML,
code: disallowCustomOptionsHtml,
}],
text: (
<p>
Leave out the <EuiCode>onCreateOption</EuiCode> prop to disallow the creation of custom options.
</p>
),
props: { EuiComboBox },
demo: <DisallowCustomOptions />,
}],
};
76 changes: 76 additions & 0 deletions src-docs/src/views/combo_box/disallow_custom_options.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React, { Component } from 'react';

import {
EuiComboBox,
} from '../../../../src/components';

export default class extends Component {
constructor(props) {
super(props);

this.options = [{
value: 'titan',
label: 'Titan',
'data-test-subj': 'titanOption',
}, {
value: 'enceladus',
label: 'Enceladus',
}, {
value: 'mimas',
label: 'Mimas',
}, {
value: 'dione',
label: 'Dione',
}, {
value: 'iapetus',
label: 'Iapetus',
}, {
value: 'phoebe',
label: 'Phoebe',
}, {
value: 'rhea',
label: 'Rhea',
}, {
value: 'pandora',
label: 'Pandora is one of Saturn\'s moons, named for a Titaness of Greek mythology',
}, {
value: 'tethys',
label: 'Tethys',
}, {
value: 'hyperion',
label: 'Hyperion',
}];

this.state = {
searchValue: '',
isPopoverOpen: false,
selectedOptions: [this.options[2], this.options[4]],
};
}

onChange = (selectedOptions) => {
this.setState({
searchValue: '',
selectedOptions,
});
};

onSearchChange = (searchValue) => {
this.setState({
searchValue,
});
};

render() {
const { searchValue, selectedOptions } = this.state;
return (
<EuiComboBox
options={this.options}
selectedOptions={selectedOptions}
onChange={this.onChange}
onSearchChange={this.onSearchChange}
searchValue={searchValue}
/>
);
}
}
1 change: 0 additions & 1 deletion src-docs/src/views/combo_box/groups.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ export default class extends Component {
}

onChange = (selectedOptions) => {
// TODO: Encapsulate searchValue within the combo box.
this.setState({
searchValue: '',
selectedOptions,
Expand Down
28 changes: 19 additions & 9 deletions src/components/combo_box/combo_box.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export class EuiComboBox extends Component {
searchValue: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
onSearchChange: PropTypes.func.isRequired,
onCreateOption: PropTypes.func.isRequired,
onCreateOption: PropTypes.func,
}

static defaultProps = {
Expand Down Expand Up @@ -214,6 +214,10 @@ export class EuiComboBox extends Component {
break;

case comboBoxKeyCodes.ENTER:
if (!this.props.onCreateOption) {
return;
}

// Don't create the value if it's already been selected.
if (getSelectedOptionForSearchValue(this.props.searchValue, this.props.selectedOptions)) {
return;
Expand Down Expand Up @@ -401,7 +405,7 @@ export class EuiComboBox extends Component {
}

renderList() {
const { options, searchValue } = this.props;
const { options, searchValue, onCreateOption } = this.props;
const { matchingOptions, optionToGroupMap } = this.state;

let emptyStateContent;
Expand All @@ -411,15 +415,21 @@ export class EuiComboBox extends Component {
} else if (this.areAllOptionsSelected()) {
emptyStateContent = <p>You&rsquo;ve selected all available options</p>;
} else if (matchingOptions.length === 0) {
const selectedOptionForValue = getSelectedOptionForSearchValue(searchValue, this.props.selectedOptions);
if (selectedOptionForValue) {
// Disallow duplicate custom options.
emptyStateContent = (
<p><strong>{selectedOptionForValue.value}</strong> has already been added</p>
);
if (onCreateOption) {
const selectedOptionForValue = getSelectedOptionForSearchValue(searchValue, this.props.selectedOptions);
if (selectedOptionForValue) {
// Disallow duplicate custom options.
emptyStateContent = (
<p><strong>{selectedOptionForValue.value}</strong> has already been added</p>
);
} else {
emptyStateContent = (
<p>Hit <EuiCode>ENTER</EuiCode> to add <strong>{searchValue}</strong> as a custom option</p>
);
}
} else {
emptyStateContent = (
<p>Hit <EuiCode>ENTER</EuiCode> to add <strong>{searchValue}</strong> as a custom option</p>
<p><strong>{searchValue}</strong> doesn&rsquo;t match any options</p>
);
}
}
Expand Down

0 comments on commit 1d34369

Please sign in to comment.