Skip to content

Instantly share code, notes, and snippets.

@igrek8
Created February 9, 2018 07:36
Show Gist options
  • Save igrek8/a233d3fda10b11b9c60e9847134a58c0 to your computer and use it in GitHub Desktop.
Save igrek8/a233d3fda10b11b9c60e9847134a58c0 to your computer and use it in GitHub Desktop.
Simple implementation of AutoComplete & Select in Material UI with Redux Form
import React from 'react';
import { Field, reduxForm } from 'redux-form';
import { AutoComplete, FlatButton } from 'material-ui';
// Component
const mapError = (
{
meta: { touched, error, warning } = {},
input,
...props
},
errorProp = 'errorText',
) =>
(touched && (error || warning)
? {
...props,
...input,
[errorProp]: error || warning,
}
: { ...input, ...props });
class SelectAutoComplete extends React.Component {
constructor(props) {
super(props);
const searchText = props.input.value;
this.state = { searchText };
}
onUpdateInput = (searchText) => {
const { input } = this.props;
const { onChange } = input;
this.setState({ searchText }, () => {
onChange(this.getSelectedIndex());
});
}
getSelectedIndex = () => {
const { dataSource, dataSourceConfig, filter } = this.props;
const searchText = this.state.searchText;
const selectedIndex = dataSource.findIndex((item, index) => {
switch (typeof item) {
case 'string':
return searchText === item;
case 'object':
if (item && typeof item[dataSourceConfig.text] === 'string') {
const itemText = item[dataSourceConfig.text];
return searchText === itemText;
}
break;
default: // Do nothing
}
return false;
});
return selectedIndex;
}
render() {
const { input, onUpdateInput } = this.props;
const { onChange, onBlur } = input;
return (
<AutoComplete
{ ...mapError(this.props) }
searchText={ this.state.searchText }
onNewRequest={ (value, index) => onChange(index) }
onBlur={ () => onBlur(this.getSelectedIndex()) }
onChange={ this.onUpdateInput }
onUpdateInput={ (searchText) => {
this.onUpdateInput(searchText);
if (onUpdateInput) {
onUpdateInput(searchText);
}
} }
/>
);
}
}
// Real example
const mapFetchedItemsToAutoComplete = {
value: 'id', text: 'name',
};
const UIForm = props => (
<form
onSubmit={ props.handleSubmit }
>
<Field
name="field1"
component={ SelectAutoComplete }
dataSourceConfig={ mapFetchedItemsToAutoComplete }
dataSource={ props.dataSource }
openOnFocus
filter={ AutoComplete.fuzzyFilter }
/>
<FlatButton
primary
label="Submit"
type="submit"
style={ { marginLeft: 15 } }
/>
</form>
);
const formValidator = (values) => {
const errors = {};
if (typeof values.field1 === 'undefined' || values.field1 === -1) {
errors.field1 = 'None of the items has been selected';
}
return errors;
};
const Form = reduxForm({
form: 'form1',
validate: formValidator,
})(UIForm);
class Application extends React.Component {
constructor(props) {
super(props);
this.state = {
dataSource: [
{ id: 1, name: 'Solution' },
{ id: 2, name: 'Problem' },
{ id: 3, name: 'Fix' },
],
};
}
componentWillMount() {
const interval = setInterval(() => {
if (this.state.dataSource.length > 10) {
clearInterval(interval);
return;
}
const id = this.state.dataSource.length + 1;
this.setState({
dataSource: [
...this.state.dataSource,
{ id, name: `Solution ${id}` },
],
});
}, 1000);
setTimeout(() => {
this.setState({
dataSource: this.state.dataSource.filter(e => e.name !== 'Fix'),
});
}, 3000);
}
render() {
return (
<Form
dataSource={ this.state.dataSource.sort((a, b) => a.name > b.name) }
onSubmit={ (values) => alert(JSON.stringify(values, null, 2)) }
/>
);
}
}
export default () => (
<Application />
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment