Skip to content

Commit

Permalink
Add option to show new creatable item as first or last option (#1436)
Browse files Browse the repository at this point in the history
  • Loading branch information
Stenerson authored and jossmac committed Jul 4, 2018
1 parent cd8d20b commit a3a977d
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 4 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <br> `false`: Show new option at bottom of list |

### Methods

Expand Down
24 changes: 23 additions & 1 deletion examples/src/components/Creatable.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ var CreatableDemo = createClass({
},
getInitialState () {
return {
atTop: true,
multi: true,
multiValue: [],
options: [
Expand All @@ -30,7 +31,7 @@ var CreatableDemo = createClass({
}
},
render () {
const { multi, multiValue, options, value } = this.state;
const { atTop, multi, multiValue, options, value } = this.state;
return (
<div className="section">
<h3 className="section-heading">{this.props.label} <a href="https://github.com/JedWatson/react-select/tree/master/examples/src/components/Creatable.js">(Source)</a></h3>
Expand All @@ -39,6 +40,7 @@ var CreatableDemo = createClass({
options={options}
onChange={this.handleOnChange}
value={multi ? multiValue : value}
showNewOptionAtTop={atTop}
/>
<div className="hint">{this.props.hint}</div>
<div className="checkbox-list">
Expand All @@ -61,6 +63,26 @@ var CreatableDemo = createClass({
<span className="checkbox-label">Single Value</span>
</label>
</div>
<div className="checkbox-list">
<label className="checkbox">
<input
type="radio"
className="checkbox-control"
checked={atTop}
onChange={() => this.setState({ atTop: true })}
/>
<span className="checkbox-label">New option at top</span>
</label>
<label className="checkbox">
<input
type="radio"
className="checkbox-control"
checked={!atTop}
onChange={() => this.setState({ atTop: false })}
/>
<span className="checkbox-label">New option at bottom</span>
</label>
</div>
</div>
);
}
Expand Down
16 changes: 13 additions & 3 deletions src/Creatable.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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);
}
}
}

Expand Down Expand Up @@ -246,7 +250,8 @@ CreatableSelect.defaultProps = {
menuRenderer: defaultMenuRenderer,
newOptionCreator,
promptTextCreator,
shouldKeyDownEventCreateNewOption
shouldKeyDownEventCreateNewOption,
showNewOptionAtTop: true
};

CreatableSelect.propTypes = {
Expand Down Expand Up @@ -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;
11 changes: 11 additions & 0 deletions test/Creatable-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit a3a977d

Please sign in to comment.