diff --git a/examples/src/app.js b/examples/src/app.js
index ed588679f0..5123bbde78 100644
--- a/examples/src/app.js
+++ b/examples/src/app.js
@@ -10,6 +10,7 @@ import CustomRender from './components/CustomRender';
import Multiselect from './components/Multiselect';
import NumericSelect from './components/NumericSelect';
import States from './components/States';
+import AllowCreate from './components/AllowCreate';
ReactDOM.render(
@@ -19,9 +20,7 @@ ReactDOM.render(
- {/*
-
- */}
+
,
document.getElementById('example')
);
diff --git a/examples/src/components/AllowCreate.js b/examples/src/components/AllowCreate.js
new file mode 100644
index 0000000000..161d09dd44
--- /dev/null
+++ b/examples/src/components/AllowCreate.js
@@ -0,0 +1,61 @@
+import React from 'react';
+import Select from 'react-select';
+
+const FLAVOURS = [
+ { label: 'Chocolate', value: 'chocolate' },
+ { label: 'Vanilla', value: 'vanilla' },
+ { label: 'Strawberry', value: 'strawberry' },
+ { label: 'Caramel', value: 'caramel' },
+ { label: 'Cookies and Cream', value: 'cookiescream' },
+ { label: 'Peppermint', value: 'peppermint' },
+];
+
+var AllowCreate = React.createClass({
+ displayName: 'AllowCreate',
+
+ propTypes: {
+ allowCreate: React.PropTypes.bool,
+ label: React.PropTypes.string,
+ },
+
+ getInitialState () {
+ return {
+ disabled: false,
+ crazy: false,
+ options: FLAVOURS,
+ value: [],
+ };
+ },
+
+ onLabelClick (data, event) {
+ console.log(data, event);
+ },
+
+ handleSelectChange (value){
+ this.setState({ value });
+ },
+
+ renderHint () {
+ return (
+ Create options in tag mode
+ );
+ },
+
+ render () {
+ return (
+
+
{this.props.label}
+
+ {this.renderHint()}
+
+ );
+ }
+});
+
+module.exports = AllowCreate;
\ No newline at end of file
diff --git a/src/Option.js b/src/Option.js
index 595c571359..daa2de9949 100644
--- a/src/Option.js
+++ b/src/Option.js
@@ -11,6 +11,7 @@ const Option = React.createClass({
onFocus: React.PropTypes.func, // method to handle mouseEnter on option element
onUnfocus: React.PropTypes.func, // method to handle mouseLeave on option element
option: React.PropTypes.object.isRequired, // object that is base for that option
+ addLabelText: React.PropTypes.string, // text to display with value while creating new option
},
blockEvent (event) {
event.preventDefault();
@@ -39,7 +40,6 @@ const Option = React.createClass({
render () {
var { option } = this.props;
var className = classNames(this.props.className, option.className);
-
return option.disabled ? (
- {this.props.children}
+ { option.create ? this.props.addLabelText.replace('{label}', option.label) : this.props.children }
);
}
diff --git a/src/Select.js b/src/Select.js
index f82dda18a5..41165292de 100644
--- a/src/Select.js
+++ b/src/Select.js
@@ -582,9 +582,19 @@ const Select = React.createClass({
},
renderMenu (options, valueArray, focusedOption) {
- if (options && options.length) {
+ if (options && options.length || this.props.allowCreate) {
let Option = this.props.optionComponent;
let renderLabel = this.props.optionRenderer || this.getOptionLabel;
+ let inputValue = this.state.inputValue.trim();
+ if (this.props.allowCreate && inputValue) {
+ options = options.slice();
+ let newOption = this.props.newOptionCreator ? this.props.newOptionCreator(inputValue) : {
+ value: inputValue,
+ label: inputValue,
+ create: true
+ };
+ options.unshift(newOption);
+ }
return options.map((option, i) => {
let isSelected = valueArray && valueArray.indexOf(option) > -1;
let isFocused = option === focusedOption;
@@ -606,12 +616,15 @@ const Select = React.createClass({
option={option}
isSelected={isSelected}
ref={optionRef}
+ addLabelText={this.props.addLabelText}
>
{renderLabel(option)}
);
});
- } else {
+ } else if (this.props.allowCreate){
+
+ } else{
return (
{this.props.noResultsText}
diff --git a/test/Async-test.js b/test/Async-test.js
index fe74bfd7ff..ec80fa5311 100644
--- a/test/Async-test.js
+++ b/test/Async-test.js
@@ -178,7 +178,7 @@ describe('Async', () => {
noResultsText="Searching..."
placeholder="Loading..."
/>);
- })
+ });
});
describe('with a cache', () => {
diff --git a/test/Select-test.js b/test/Select-test.js
index 3faf2defba..c287ddca72 100644
--- a/test/Select-test.js
+++ b/test/Select-test.js
@@ -1047,7 +1047,7 @@ describe('Select', () => {
describe('with allowCreate=true', () => {
// TODO: allowCreate hasn't been implemented yet in 1.x
- return;
+ // return;
beforeEach(() => {
@@ -1060,7 +1060,8 @@ describe('Select', () => {
{ value: 'three', label: 'Three' },
{ value: 'zzzzz', label: 'test value' }
];
-
+ setValueProp('xyz');
+
// Render an instance of the component
wrapper = createControlWithWrapper({
value: 'one',
@@ -1068,12 +1069,13 @@ describe('Select', () => {
allowCreate: true,
searchable: true,
addLabelText: 'Add {label} to values?'
+ }, {
+ wireUpOnChangeToValue: true
});
});
it('has an "Add xyz" option when entering xyz', () => {
typeSearchText('xyz');
-
expect(ReactDOM.findDOMNode(instance), 'queried for', '.Select-menu .Select-option',
'to have items satisfying', 'to have text', 'Add xyz to values?');
});
@@ -1108,28 +1110,12 @@ describe('Select', () => {
it('displays an add option when a value with spaces is entered', () => {
- typeSearchText('got');
+ typeSearchText(' got ');
expect(ReactDOM.findDOMNode(instance).querySelectorAll('.Select-menu .Select-option')[0],
'to have text', 'Add got to values?');
});
- it('displays an add option when a value with spaces is entered', () => {
-
- typeSearchText('got');
-
- expect(ReactDOM.findDOMNode(instance).querySelectorAll('.Select-menu .Select-option')[0],
- 'to have text', 'Add got to values?');
- });
-
- it('displays an add option when a label with spaces is entered', () => {
-
- typeSearchText('test');
-
- expect(ReactDOM.findDOMNode(instance).querySelectorAll('.Select-menu .Select-option')[0],
- 'to have text', 'Add test to values?');
- });
-
it('does not display the option label when an existing value is entered', () => {
typeSearchText('zzzzz');