Я использую материалы, которые пользовательский интерфейс реагирует, использует редукцию, повторную проверку и автозаполнение, чтобы реализовать компонент автозаполнения с помощью API мест Google. Мне удалось реализовать поиск мест, но я не могу заставить работать с ошибками так, как с остальными моими входами.
Кроме того, всякий раз, когда я набираю что-то в поле и выбираю место из выпадающего списка, очищаю поле и щелкаю по нему, оно сбрасывается до последнего значения, которое у него было, вместо того, чтобы оставить поле пустым и отображать ошибку.
Я попытался использовать автозаполнение реагирующих мест, и оно работает, как и ожидалось, но в нем отсутствует дизайн материала, который мне требуется, так что на самом деле это не вариант.
Поскольку mui-place-autocomplete имеет несколько реквизитов, в том числе textFieldProps, должен быть способ использовать реквизит ошибки из текстового поля и использовать его, но я не уверен, как это сделать.
Вот мой код на случай, если он поможет показать, чего я пытаюсь достичь.
PlaceInput.jsx
import React, { Component } from 'react';
import MUIPlacesAutocomplete from 'mui-places-autocomplete';
import Script from 'react-load-script';
/* MUI Components */
import FormControl from '@material-ui/core/FormControl';
import FormHelperText from '@material-ui/core/FormHelperText';
class PlaceInput extends Component {
state = {
scriptLoaded: false
}
handleScriptLoad = () => {
this.setState({
scriptLoaded: true
})
}
render() {
const { onSuggestionSelected, createAutocompleteRequest, meta: { touched, error }, ...other } = this.props;
return (
<FormControl error={touched && !!error} margin="normal" fullWidth>
<Script
url="https://maps.googleapis.com/maps/api/js?key=API_KEY&libraries=places"
onLoad={this.handleScriptLoad}
/>
{
this.state.scriptLoaded &&
<MUIPlacesAutocomplete
onSuggestionSelected={onSuggestionSelected}
createAutocompleteRequest={createAutocompleteRequest}
renderTarget={() => (<div />)}
textFieldProps={{ ...other }}
/>
}
{
touched &&
error &&
<FormHelperText style={{ color: '#f44336' }}>{error}</FormHelperText>
}
</FormControl>
)
}
}
export default PlaceInput;
EventForm.jsx
/*global google*/
import { reduxForm, Field } from 'redux-form';
import { composeValidators, combineValidators, isRequired, hasLengthGreaterThan } from 'revalidate';
import { geocodeBySuggestion } from 'mui-places-autocomplete';
/* Form Inputs */
import PlaceInput from '../../../app/common/form/PlaceInput';
const validate = combineValidators({
title: isRequired({ message: 'The event title is required' }),
category: isRequired({ message: 'Please provide a category' }),
description: composeValidators(
isRequired({ message: 'Please enter a description' }),
hasLengthGreaterThan(4)({ message: 'Description needs to be at least 5 characters' })
)(),
city: isRequired('City'),
venue: isRequired('Venue'),
date: isRequired('Date')
});
class EventForm extends Component {
state = {
cityLatLng: {},
venueLatLng: {},
scriptLoaded: false
}
createAutocompleteRequestForCities = (inputValue) => {
return {
input: inputValue,
types: ['(cities)']
}
}
createAutocompleteRequestForEstablishments = (inputValue) => {
return {
input: inputValue,
types: ['establishment'],
location: new google.maps.LatLng(this.state.cityLatLng),
radius: 1000
}
}
handleScriptLoad = () => {
this.setState({
scriptLoaded: true
})
}
render() {
const { classes, invalid, submitting, pristine } = this.props;
return (
<form onSubmit={this.props.handleSubmit(this.onFormSubmit)}>
<Field
fullWidth
onSuggestionSelected={this.onSuggestionSelectedCity}
createAutocompleteRequest={this.createAutocompleteRequestForCities}
name="city"
helperText="Required field"
component={PlaceInput}
label="Event City"
/>
{
this.state.scriptLoaded &&
<Field
fullWidth
onSuggestionSelected={this.onSuggestionSelectedVenue}
createAutocompleteRequest {this.createAutocompleteRequestForEstablishments}
name="venue"
helperText="Required field"
component={PlaceInput}
label="Event Venue"
/>
}
)
}
}
EventForm.propTypes = {
classes: PropTypes.object.isRequired,
};
const mapStateToProps = (state, ownProps) => {
const eventId = ownProps.match.params.id;
let event = {};
if (eventId && state.events.length > 0) {
event = state.events.filter(event => event.id === eventId)[0];
}
return {
initialValues: event
}
}
const actions = {
createEvent,
updateEvent,
deleteEvent
}
export default compose(
connect(mapStateToProps, actions),
reduxForm({ form: 'reduxForm', enableReinitialize: true, validate }),
withStyles(styles)
)(EventForm);