Skip to content

Instantly share code, notes, and snippets.

@srph
Last active January 30, 2017 06:00
Show Gist options
  • Select an option

  • Save srph/c7a3dd02d632fcbf86753933ac39f5a4 to your computer and use it in GitHub Desktop.

Select an option

Save srph/c7a3dd02d632fcbf86753933ac39f5a4 to your computer and use it in GitHub Desktop.

usage

<DynamicSelect endpoint="/countries"
  placeholder="Select country"
  loading="Loading countries..."
  value={country}
  onChange={handler}
  id="my-select"
  name="my-select" />

with variables

This select also supports if your select depends on another value. For example, if you're loading breed of either a cat or a dog. Here's an example below:

<DynamicSelect endpoint="/breeds/:variable"
  variable={kind}
  placeholder="Select breed"
  loading="Loading breeds for :variable..."
  value={breed}
  onChange={handler}
  id="my-select" 
  name="my-select" />

why not a library?

I really don't have the time now.

import React, {Component, PropTypes} from 'react';
import axios from 'axios';
import omit from 'lodash/omit';
export default class DynamicSelect extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
options: [],
error: ''
};
}
componentDidMount() {
// We'll stop the initial loading if the variable
// hasn't been filled yet. (Which is a blank string if there's a variable)
if ( typeof this.props.variable === 'string' && !this.props.variable.length ) {
return;
}
this.options(this.props);
}
componentWillReceiveProps(nextProps) {
if ( this.props.variable !== nextProps.variable ) {
this.options(nextProps);
}
}
render() {
const {loading, error, options} = this.state;
const props = omit(this.props, ['loading', 'placeholder', 'options', 'endpoint', 'variable']);
return (
<select {...props}>
{loading && <option value="0">{this.props.loading.replace(':variable', this.props.variable)}</option>}
{error.length && <option value="0">{error}</option>}
{!error.length && !loading && <option value="0">{this.props.placeholder}</option>}
{options.map((option, i) =>
<option value={option.value} key={option.value}>{option.display}</option>
)}
</select>
);
}
options(props) {
if ( this.state.loading ) {
return;
}
this.setState({ loading: true });
return axios.get(props.endpoint.replace(':variable', props.variable))
.then((res) => {
this.setState({
options: Object.keys(res.data).map((key) => ({
value: key,
display: res.data[key]
})),
loading: false
});
}, (err) => {
this.setState({
loading: false,
error: (() => {
if ( err.response.status ) {
return 'Oops! An error occurred with the server.';
}
if ( err.response.status === 422 ) {
return 'Uh oh, it looks like you filled some fields incorrect.';
}
return 'Mm, it appears that there\'s an issue with your connection.'
})()
});
});
}
}
DynamicSelect.propTypes = {
placeholder: PropTypes.string,
loading: PropTypes.string,
variable: PropTypes.string,
endpoint: PropTypes.string.isRequired
};
DynamicSelect.defaultProps = {
placeholder: 'Select something...',
loading: 'Loading...'
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment