Skip to content

Instantly share code, notes, and snippets.

@MrLeebo
Last active February 4, 2016 16:53
Show Gist options
  • Save MrLeebo/db40779fecffda785d85 to your computer and use it in GitHub Desktop.
Save MrLeebo/db40779fecffda785d85 to your computer and use it in GitHub Desktop.
Example using Autosuggest with jquery-ui to fix the suggestions menu position inside a scrollable container
/*global __IS_TEST__*/
import _ from 'lodash';
import React from 'react';
const { array, string, func, number } = React.PropTypes;
import { findDOMNode } from 'react-dom';
import Autosuggest from 'react-autosuggest';
if (!__IS_TEST__) require('jquery-ui');
export default React.createClass({
propTypes: {
options: array.isRequired,
value: string,
onChange: func.isRequired,
maxSuggestions: number
},
getDefaultProps() {
return { maxSuggestions: 5, value: '' }
},
getInitialState() {
return { suggestions: this.getSuggestions(this.props.value) }
},
componentDidMount() {
this.fixSuggestionsPosition();
},
componentDidUpdate() {
this.fixSuggestionsPosition();
},
fixSuggestionsPosition() {
if (__IS_TEST__) return;
// I feel like there should be a better way to do this.
window.requestAnimationFrame(() => {
const component = findDOMNode(this.refs.autosuggest);
const menu = $('.autosuggest-suggestions', component);
const input = $('input', component);
menu.position({
my: "left top",
at: "left bottom",
of: input,
collision: "fit"
});
});
},
onSuggestionsUpdateRequested({value}) {
this.setState({ suggestions: this.getSuggestions(value)})
},
getSuggestionValue(suggestion) {
return suggestion;
},
renderSuggestion(suggestion) {
return <a href='#'>{suggestion}</a>
},
getSuggestions(value='') {
value = value && value.trim().toLowerCase();
return value && _.take(this.props.options.filter(o => o.toLowerCase().includes(value)), this.props.maxSuggestions) || [];
},
shouldRenderSuggestions(value='') {
this.fixSuggestionsPosition();
return value && value.trim().length > 0;
},
onChange(e, {newValue}) {
e.preventDefault();
this.props.onChange(newValue);
},
onSuggestionSelected(e, {suggestionValue}) {
e.preventDefault();
this.props.onChange(suggestionValue);
},
render() {
const { options, value, ...passableProps } = this.props;
const theme = {
container: 'autosuggest dropdown',
containerOpen: 'open',
input: 'autosuggest-input form-control',
suggestionsContainer: 'autosuggest-suggestions dropdown-menu',
suggestion: '',
suggestionFocused: 'active'
};
const inputProps = {
value: value,
className: 'form-control',
...passableProps,
onChange: this.onChange
};
return (
<Autosuggest
ref='autosuggest'
suggestions={this.getSuggestions(value)}
onSuggestionsUpdateRequested={this.onSuggestionsUpdateRequested}
onSuggestionSelected={this.onSuggestionSelected}
getSuggestionValue={this.getSuggestionValue}
renderSuggestion={this.renderSuggestion}
shouldRenderSuggestions={this.shouldRenderSuggestions}
inputProps={inputProps}
theme={theme}/>
);
}
})
.scrollable-menu {
height: auto;
max-height: 50vh;
overflow-y: auto;
}
.autosuggest {
position: static;
margin-right: 20px;
}
.autosuggest-suggestions {
position: absolute;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment