From 518419c74c25bedbf8fb9d036a229d421e7bd426 Mon Sep 17 00:00:00 2001 From: Elizabet Oliveira Date: Fri, 17 Jul 2020 17:57:04 +0100 Subject: [PATCH] Updated EuiComboBox to allow the options list to open for single selection custom options (#3706) * Fixing includes to return true when object exists in array * changelog * Allowing list to open for single selection custom options * Updated changelog * PR review * Improving example * Improving example * Addind isClearable * Improving examples * Improving explanation text * Adding note * Addressing PR issues * Update src-docs/src/views/combo_box/combo_box_example.js Co-authored-by: Caroline Horn <549577+cchaos@users.noreply.github.com> * Update src-docs/src/views/combo_box/combo_box_example.js Co-authored-by: Caroline Horn <549577+cchaos@users.noreply.github.com> * Snippet Co-authored-by: Caroline Horn <549577+cchaos@users.noreply.github.com> --- CHANGELOG.md | 1 + .../src/views/combo_box/combo_box_example.js | 46 ++++++++++++- .../src/views/combo_box/single_selection.js | 1 - .../single_selection_custom_options.js | 67 +++++++++++++++++++ src/components/combo_box/combo_box.tsx | 27 ++------ 5 files changed, 117 insertions(+), 25 deletions(-) create mode 100644 src-docs/src/views/combo_box/single_selection_custom_options.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 53a55dd685d..c11d7f0a5ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## [`master`](https://github.com/elastic/eui/tree/master) +- Updated `EuiComboBox` to allow the options list to open for single selection custom options ([#3706](https://github.com/elastic/eui/pull/3706)) - Added `useEuiI18n` hook for localization ([#3749](https://github.com/elastic/eui/pull/3749)) **Bug fixes** diff --git a/src-docs/src/views/combo_box/combo_box_example.js b/src-docs/src/views/combo_box/combo_box_example.js index 4133c4cf74b..eeed2b83620 100644 --- a/src-docs/src/views/combo_box/combo_box_example.js +++ b/src-docs/src/views/combo_box/combo_box_example.js @@ -83,7 +83,20 @@ const singleSelectionSnippet = ``; + +import SingleSelectionCustomOptions from './single_selection_custom_options'; +const singleSelectionCustomOptionsSource = require('!!raw-loader!./single_selection_custom_options'); +const singleSelectionCustomOptionsHtml = renderToHtml( + SingleSelectionCustomOptions +); +const singleSelectionCustomOptionsSnippet = ``; import DisallowCustomOptions from './disallow_custom_options'; @@ -405,6 +418,37 @@ export const ComboBoxExample = { snippet: singleSelectionSnippet, demo: , }, + { + title: 'Single selection with custom options', + source: [ + { + type: GuideSectionTypes.JS, + code: singleSelectionCustomOptionsSource, + }, + { + type: GuideSectionTypes.HTML, + code: singleSelectionCustomOptionsHtml, + }, + ], + text: ( + +

+ You can allow the user to select a single option and also allow the + creation of custom options. To do that, use the{' '} + singleSelection in conjunction with the{' '} + onCreateOption prop. +

+

+ Note: Creating custom options might not be obvious + to the user, so provide help text explaining that this option is + available. +

+
+ ), + props: { EuiComboBox }, + snippet: singleSelectionCustomOptionsSnippet, + demo: , + }, { title: 'Disallowing custom options', source: [ diff --git a/src-docs/src/views/combo_box/single_selection.js b/src-docs/src/views/combo_box/single_selection.js index 38afbf8c1a1..3da807d85b5 100644 --- a/src-docs/src/views/combo_box/single_selection.js +++ b/src-docs/src/views/combo_box/single_selection.js @@ -59,7 +59,6 @@ export default () => { options={options} selectedOptions={selectedOptions} onChange={onChange} - isClearable={false} /> ); diff --git a/src-docs/src/views/combo_box/single_selection_custom_options.js b/src-docs/src/views/combo_box/single_selection_custom_options.js new file mode 100644 index 00000000000..2f2cc1e9b2c --- /dev/null +++ b/src-docs/src/views/combo_box/single_selection_custom_options.js @@ -0,0 +1,67 @@ +import React, { useState } from 'react'; + +import { EuiComboBox, EuiFormRow } from '../../../../src/components'; + +const options = [ + { + label: 'Software Developer', + 'data-test-subj': 'softDevOption', + }, + { + label: 'Mobile Developer', + }, + { + label: 'Javascript Engineer', + }, + { + label: 'UX Designer', + }, + { + label: 'UI Designer', + }, + { + label: 'Product Designer', + }, + { + label: 'QA Engineer', + }, +]; + +export default () => { + const [selectedOptions, setSelected] = useState([options[2]]); + + const onChange = selectedOptions => { + // We should only get back either 0 or 1 options. + setSelected(selectedOptions); + }; + + const onCreateOption = (searchValue = []) => { + const normalizedSearchValue = searchValue.trim().toLowerCase(); + + if (!normalizedSearchValue) { + return; + } + + const newOption = { + label: searchValue, + }; + + // Select the option. + setSelected([newOption]); + }; + + return ( + + + + ); +}; diff --git a/src/components/combo_box/combo_box.tsx b/src/components/combo_box/combo_box.tsx index 0c5bd260bc1..d964e7ccdb0 100644 --- a/src/components/combo_box/combo_box.tsx +++ b/src/components/combo_box/combo_box.tsx @@ -473,10 +473,7 @@ export class EuiComboBox extends Component< this.clearSearchValue(); - if ( - this.isSingleSelectionCustomOption() || - (Boolean(singleSelection) && matchingOptions.length < 1) - ) { + if (Boolean(singleSelection)) { // Adding a custom option to a single select that does not appear in the list of options this.closeList(); } @@ -516,29 +513,13 @@ export class EuiComboBox extends Component< return flattenOptions.length === numberOfSelectedOptions; }; - isSingleSelectionCustomOption = () => { - const { - onCreateOption, - options, - selectedOptions, - singleSelection, - } = this.props; - // The selected option of a single select is custom and does not appear in the list of options - return ( - Boolean(singleSelection) && - onCreateOption && - selectedOptions.length > 0 && - !options.includes(selectedOptions[0]) - ); - }; - onComboBoxFocus: FocusEventHandler = event => { if (this.props.onFocus) { this.props.onFocus(event); } - if (!this.isSingleSelectionCustomOption()) { - this.openList(); - } + + this.openList(); + this.setState({ hasFocus: true }); };