From a3a977d6b63372cb1b2e4ab781bdb36daa5e448f Mon Sep 17 00:00:00 2001 From: Matt Stenerson Date: Wed, 4 Jul 2018 02:14:35 -0500 Subject: [PATCH] Add option to show new creatable item as first or last option (#1436) --- README.md | 1 + examples/src/components/Creatable.js | 24 +++++++++++++++++++++++- src/Creatable.js | 16 +++++++++++++--- test/Creatable-test.js | 11 +++++++++++ 4 files changed, 48 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 69a9f86361..571f9a2016 100644 --- a/README.md +++ b/README.md @@ -460,6 +460,7 @@ function onInputKeyDown(event) { | `onNewOptionClick` | function | new option click handler, it calls when new option has been selected. `function(option) {}` | | `shouldKeyDownEventCreateNewOption` | function | Decides if a keyDown event (eg its `keyCode`) should result in the creation of a new option. ENTER, TAB and comma keys create new options by default. Expected signature: `({ keyCode: number }): boolean` | | `promptTextCreator` | function | Factory for overriding default option creator prompt label. By default it will read 'Create option "{label}"'. Expected signature: `(label: String): String` | +| `showNewOptionAtTop` | boolean | `true`: (Default) Show new option at top of list
`false`: Show new option at bottom of list | ### Methods diff --git a/examples/src/components/Creatable.js b/examples/src/components/Creatable.js index 50a8baaf2b..6082241873 100644 --- a/examples/src/components/Creatable.js +++ b/examples/src/components/Creatable.js @@ -11,6 +11,7 @@ var CreatableDemo = createClass({ }, getInitialState () { return { + atTop: true, multi: true, multiValue: [], options: [ @@ -30,7 +31,7 @@ var CreatableDemo = createClass({ } }, render () { - const { multi, multiValue, options, value } = this.state; + const { atTop, multi, multiValue, options, value } = this.state; return (

{this.props.label} (Source)

@@ -39,6 +40,7 @@ var CreatableDemo = createClass({ options={options} onChange={this.handleOnChange} value={multi ? multiValue : value} + showNewOptionAtTop={atTop} />
{this.props.hint}
@@ -61,6 +63,26 @@ var CreatableDemo = createClass({ Single Value
+
+ + +
); } diff --git a/src/Creatable.js b/src/Creatable.js index ec1fc44163..d5edac4c21 100644 --- a/src/Creatable.js +++ b/src/Creatable.js @@ -42,7 +42,7 @@ class CreatableSelect extends React.Component { } filterOptions (...params) { - const { filterOptions, isValidNewOption, promptTextCreator } = this.props; + const { filterOptions, isValidNewOption, promptTextCreator, showNewOptionAtTop } = this.props; // TRICKY Check currently selected options as well. // Don't display a create-prompt for a value that's selected. @@ -76,7 +76,11 @@ class CreatableSelect extends React.Component { valueKey: this.valueKey }); - filteredOptions.unshift(this._createPlaceholderOption); + if (showNewOptionAtTop) { + filteredOptions.unshift(this._createPlaceholderOption); + } else { + filteredOptions.push(this._createPlaceholderOption); + } } } @@ -246,7 +250,8 @@ CreatableSelect.defaultProps = { menuRenderer: defaultMenuRenderer, newOptionCreator, promptTextCreator, - shouldKeyDownEventCreateNewOption + shouldKeyDownEventCreateNewOption, + showNewOptionAtTop: true }; CreatableSelect.propTypes = { @@ -294,6 +299,11 @@ CreatableSelect.propTypes = { // Decides if a keyDown event (eg its `keyCode`) should result in the creation of a new option. shouldKeyDownEventCreateNewOption: PropTypes.func, + + // Where to show prompt/placeholder option text. + // true: new option prompt at top of list (default) + // false: new option prompt at bottom of list + showNewOptionAtTop: React.PropTypes.bool, }; export default CreatableSelect; diff --git a/test/Creatable-test.js b/test/Creatable-test.js index 488eb1f78f..ce6c3f3438 100644 --- a/test/Creatable-test.js +++ b/test/Creatable-test.js @@ -66,6 +66,17 @@ describe('Creatable', () => { expect(creatableNode.querySelector('.Select-create-option-placeholder'), 'to have text', Select.Creatable.promptTextCreator('foo')); }); + it('should add a placeholder "create..." prompt as last option when showNewOptionAtTop is false', () => { + createControl({ + showNewOptionAtTop: false + }); + const searchTerm = 'Th'; + typeSearchText(searchTerm); + let nodes = creatableNode.querySelectorAll('.Select-option'); + expect(nodes, 'to have length', 2); // [Three, Create "th"?] + expect(nodes[nodes.length-1], 'to have text', Select.Creatable.promptTextCreator(searchTerm)); + }); + it('should not show a "create..." prompt if current filter text is an exact match for an existing option', () => { createControl({ isOptionUnique: () => false