diff --git a/README.md b/README.md index 27f19880ef..f3414b60bd 100644 --- a/README.md +++ b/README.md @@ -158,6 +158,7 @@ For multi-select inputs, when providing a custom `filterOptions` method, remembe clearable | bool | should it be possible to reset value clearAllText | string | title for the "clear" control when multi: true clearValueText | string | title for the "clear" control + delayAsyncMs | number | time delay before querying after an input change delimiter | string | delimiter to use to join multiple values disableCache | bool | disables the options cache for asyncOptions disabled | bool | whether the Select is disabled or not diff --git a/src/Select.js b/src/Select.js index e1124f7c03..ce4ce52e3c 100644 --- a/src/Select.js +++ b/src/Select.js @@ -26,6 +26,7 @@ var Select = React.createClass({ clearAllText: React.PropTypes.string, // title for the "clear" control when multi: true clearValueText: React.PropTypes.string, // title for the "clear" control clearable: React.PropTypes.bool, // should it be possible to reset value + delayAsyncMs: React.PropTypes.number, // time delay before querying after an input change delimiter: React.PropTypes.string, // delimiter to use to join multiple values disabled: React.PropTypes.bool, // whether the Select is disabled or not filterOption: React.PropTypes.func, // method to filter a single option: function(option, filterString) @@ -68,6 +69,7 @@ var Select = React.createClass({ clearAllText: 'Clear all', clearValueText: 'Clear value', clearable: true, + delayAsyncMs: 0, delimiter: ',', disabled: false, ignoreCase: true, @@ -103,6 +105,7 @@ var Select = React.createClass({ * - placeholder * - focusedOption */ + inputTimer: undefined, isFocused: false, isLoading: false, isOpen: false, @@ -494,23 +497,42 @@ var Select = React.createClass({ this._optionsFilterString = event.target.value; if (this.props.onInputChange) { - this.props.onInputChange(event.target.value); + this.props.onInputChange(this._optionsFilterString); } if (this.props.asyncOptions) { + var callAsyncLoad = function() { + this.loadAsyncOptions(this._optionsFilterString, { + isLoading: false, + isOpen: true + }, this._bindCloseMenuIfClickedOutside); + }.bind(this); + + if (this.props.delayAsyncMs) { + if (this.state.inputTimer) { + clearTimeout(this.state.inputTimer); + } + + var wait = setTimeout(function() { + callAsyncLoad(); + }, this.props.delayAsyncMs); + + this.setState({ + inputTimer: wait + }); + } else { + callAsyncLoad(); + } + this.setState({ isLoading: true, - inputValue: event.target.value + inputValue: this._optionsFilterString }); - this.loadAsyncOptions(event.target.value, { - isLoading: false, - isOpen: true - }, this._bindCloseMenuIfClickedOutside); } else { var filteredOptions = this.filterOptions(this.state.options); this.setState({ isOpen: true, - inputValue: event.target.value, + inputValue: this._optionsFilterString, filteredOptions: filteredOptions, focusedOption: this._getNewFocusedOption(filteredOptions) }, this._bindCloseMenuIfClickedOutside);