From 1c170d8eec941e29da66834252f93c971a035ee5 Mon Sep 17 00:00:00 2001 From: CofCat456 Date: Mon, 25 Dec 2023 11:29:49 +0800 Subject: [PATCH] feat(Dropdown): add allowReselection prop --- .../Usage/DropdownExampleAllowReselection.js | 42 +++++++++++++++++++ .../examples/modules/Dropdown/Usage/index.js | 5 +++ src/modules/Dropdown/Dropdown.d.ts | 5 +++ src/modules/Dropdown/Dropdown.js | 25 ++++++----- 4 files changed, 67 insertions(+), 10 deletions(-) create mode 100644 docs/src/examples/modules/Dropdown/Usage/DropdownExampleAllowReselection.js diff --git a/docs/src/examples/modules/Dropdown/Usage/DropdownExampleAllowReselection.js b/docs/src/examples/modules/Dropdown/Usage/DropdownExampleAllowReselection.js new file mode 100644 index 0000000000..6407fde499 --- /dev/null +++ b/docs/src/examples/modules/Dropdown/Usage/DropdownExampleAllowReselection.js @@ -0,0 +1,42 @@ +import React, { Component } from 'react' +import { Dropdown } from 'semantic-ui-react' + +const options = [ + { key: 'English', text: 'English', value: 'English' }, + { key: 'French', text: 'French', value: 'French' }, + { key: 'Spanish', text: 'Spanish', value: 'Spanish' }, + { key: 'German', text: 'German', value: 'German' }, + { key: 'Chinese', text: 'Chinese', value: 'Chinese' }, +] + +class DropdownExampleAllowReselection extends Component { + state = { options } + + handleAddition = (e, { value }) => { + this.setState((prevState) => ({ + options: [{ text: value, value }, ...prevState.options], + })) + } + + handleChange = (e, { value }) => this.setState({ currentValue: value }) + + render() { + const { currentValue } = this.state + + return ( + + ) + } +} + +export default DropdownExampleAllowReselection diff --git a/docs/src/examples/modules/Dropdown/Usage/index.js b/docs/src/examples/modules/Dropdown/Usage/index.js index f7727c56b2..0910f7875d 100644 --- a/docs/src/examples/modules/Dropdown/Usage/index.js +++ b/docs/src/examples/modules/Dropdown/Usage/index.js @@ -77,6 +77,11 @@ const DropdownUsageExamples = () => ( description='Or provide additionLabel as a component.' examplePath='modules/Dropdown/Usage/DropdownExampleAdditionLabelComponent' /> + { + makeSelectedItemActive = (e, selectedIndex, allowReselection) => { const { open, value } = this.state const { multiple } = this.props @@ -297,7 +297,8 @@ class DropdownInner extends Component { const newValue = multiple ? _.union(value, [selectedValue]) : selectedValue const valueHasChanged = multiple ? !!_.difference(newValue, value).length : newValue !== value - if (valueHasChanged) { + // when use allowReselection then can be select same value + if (allowReselection || valueHasChanged) { // notify the onChange prop that the user is trying to change value this.setState({ value: newValue }) this.handleChange(e, newValue) @@ -314,7 +315,7 @@ class DropdownInner extends Component { selectItemOnEnter = (e) => { debug('selectItemOnEnter()', keyboardKey.getKey(e)) - const { search } = this.props + const { search, allowReselection = false } = this.props const { open, selectedIndex } = this.state if (!open) { @@ -351,7 +352,7 @@ class DropdownInner extends Component { return } - const nextValue = this.makeSelectedItemActive(e, selectedIndex) + const nextValue = this.makeSelectedItemActive(e, selectedIndex, allowReselection) // This is required as selected value may be the same this.setState({ @@ -464,7 +465,7 @@ class DropdownInner extends Component { } } - handleItemClick = (e, item) => { + handleItemClick = (e, item, allowReselection) => { debug('handleItemClick()', item) const { multiple, search } = this.props @@ -489,7 +490,8 @@ class DropdownInner extends Component { : newValue !== currentValue // notify the onChange prop that the user is trying to change value - if (valueHasChanged) { + // when use allowReselection then can be select same value + if (allowReselection || valueHasChanged) { this.setState({ value: newValue }) this.handleChange(e, newValue) } @@ -522,8 +524,6 @@ class DropdownInner extends Component { } handleBlur = (e) => { - debug('handleBlur()') - // Heads up! Don't remove this. // https://github.com/Semantic-Org/Semantic-UI-React/issues/1315 const currentTarget = _.get(e, 'currentTarget') @@ -956,7 +956,7 @@ class DropdownInner extends Component { } renderOptions = () => { - const { lazyLoad, multiple, search, noResultsMessage } = this.props + const { lazyLoad, multiple, search, noResultsMessage, allowReselection = false } = this.props const { open, selectedIndex, value } = this.state // lazy load, only render options when open @@ -998,7 +998,7 @@ class DropdownInner extends Component { overrideProps: (predefinedProps) => ({ onClick: (e, item) => { predefinedProps.onClick?.(e, item) - this.handleItemClick(e, item) + this.handleItemClick(e, item, allowReselection) }, }), }, @@ -1143,6 +1143,11 @@ Dropdown.propTypes = { PropTypes.bool, ]), + /** + * Allow user to trigger onChange events even when reselecting same value. + */ + allowReselection: PropTypes.bool, + /** A Dropdown can reduce its complexity. */ basic: PropTypes.bool,