Dynamically Adding Points on a Map via Forms
In the first part of this two part series of posts, we introduced the Google Maps API, and went over how to incorporate a functional map in your app, with markers generated from your backend that dynamically route to specific pages for each location. This functionality is great for a situation where there are a finite number of points on a map, that the user should not have the power to change. For example if you wanted a map showing all the locations of a given restaurant chain, you could just have all your locations hard coded into your backend, and you could simply follow along with my last post.
However, in the fishing app that we’ve been working with, we want the user to have the ability to add markers (fishing holes) on our map via the user interface. To do this, we’re obviously going to have to start with a form component where the user can enter in the location they want to appear on the map.
As you can see in the image above, our form has two options for the user. They can choose to either enter their location via their geographic coordinates, or they can simply enter their address. The logic for the coordinates is probably going to be a bit more straight-forward since if you recall, coordinates were what we used to populate the map from our backend in the first place. However, it’s probably much more realistic that our user will simply want to enter an address or location name than coordinates, so how do we account for this sort of input? Well, let’s take a look at our form component.
At the top of our component you can see that we’ve imported something called React Geocode. This is a third party tool that allows us to easily convert an address (or location name) into longitude — latitude values, which we can then use with our Google Maps API. In addition to importing Geocode, you can see that we also set a language/region and input our API key that we acquired when we set up our map.
In our form on this component, you can see that we’ve only included the address option, since we’ve separated the two user input options into their own components. We’ll just be dealing with the address input here, since one should be easily able to manage the coordinate input, if they can deal with this address option, since the logic is similar, but with fewer steps. So for now, let’s look at this handleChange function that our form calls when the user enters an address.
To start off, the aforementioned handleChange function is going to simply take the user input and set the state of address, but remember this address is still unusable with the Google Maps API. So when the user submits their address, this handleSubmit function will deal with converting our address to useable coordinates.
This is where Geocode works its magic. Using the syntax above you simply put in your desired address in the parenthesis, then Geocode locates this on the map, and allows you to extract the latitude and longitude (lat, lng) from that location object. After this, we can pass these two values to functions which will set state for longitude and latitude.
This alone should be enough to put a new point on the map if we pass these values into our original function from vol. 1 of this series. However, in our case this marker we are creating is more than just a point on a map, it’s a location with other attributes that makes up it’s own page. So getting the longitude and latitude alone, will not allow us to create a new location element. To do this, we’re going to need more inputs, this is why you see that showStateChange() function, which works to help display a pop up modal where the rest of the form for creating a location will take be located.
In our case this modal will show have the following html form, that will handle the inputs of body of water type, description, image, etc. to go along with the longitude and latitude values that we’ve passed as props to this modal.
On submit, we’ll create a new location object that we pass to a function located in our main map page we were working with in vol. 1.
From here, it’s pretty straight forward. Now that we have this location object we can use it to optimistically render the new location, by adding it to our the array of locations in state, and then running a post request on the backend before rendering the updated map.
And there you have it! With the use of our handy-dandy Geocoder, and the passing around of some props, we can pretty easily permit users to add their own locations on our map, for any new fishing holes they encounter!