0
votes

I'm using material ui react, redux-form, revalidate and mui-places-autocomplete to implement an autocomplete component using google places API. I've managed to implement the lookup of places, but I can't seem to be able to get error handling to work like with the rest of my inputs.

Also, whenever I type something into the field and select a place from the dropdown, clear the field and click out of it, it resets to the last value it had instead of leaving the field blank and showing the error.

I tried using react-places autocomplete and it works as expected, but it lacks the material design which I require, so that isn't really an option.

Since mui-places-autocomplete has several props, including textFieldProps there should be a way to leverage the error prop from the text field and use it, but I am not sure how to do that.

Here is my code in case it helps show what I'm trying to accomplish.

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);
1
Consider cleaning up your code so that readers can focus on the question at hand.Thierry Prost
Thanks for the suggestion, I'll try. I just wanted to be as clear as possible to solve the issue.Ashtar

1 Answers

0
votes

I don't have an answer but you forgot to delete your Google API Key, be careful