Rendering a Google Map in a JavaScript Front-End: Part II

Storing and Rendering Points and Polygons on the map

Luke Menard
Analytics Vidhya
7 min readOct 8, 2019

--

In my last post, I discussed my approach to setting up a project on the Google Cloud Platform and rendering a map in a JavaScript frontend via the Google Maps JavaScript API. In this post, I’ll detail the approach that I took to generate new point and polygon data in a rendered map that persist both optimistically and pessimistically in a Ruby-on-Rails backend database.

The project that I created is a web tool to help firefighters and foresters track wildfires and plan prescribed burns. For my purposes, I wanted to give the end-user the ability to plot new point and polygon data that is editable, deletable, and persistent.

Backend

Creating a Rails API

To create persistent Google Maps point and polygon data, I first built a rails backend database and API to house the information and then retrieved the necessary data on the frontend via the API. I created a “points” model that included string/text fields for a title, description, link, as well as float fields for the point’s latitude and longitude:

I also generated a “polygons” model with the same string and text fields. However, I included fifteen distinct float fields for both the latitudes and longitudes of potential polygon vertices. This was a slightly arbitrary choice that limits the new polygons created in the app to fourteen sides.

Additionally, I created controller files for both the point and polygon models that include relevant CRUD methods and render the resulting JSON data to the Rails API.

For my purposes, running a local Rails server for frontend data retrieval was sufficient.

Frontend

Creating New Point Data

The creation of a new data point should occur when a user interacts with the map in a predetermined way. The Google Maps JavaScript API has several built-in event listeners (e.g. click, double click, mouseover) that can trigger a method(s) upon server-side completion of the selected action. I built an event listener that responds to a mouse double click on the map display by creating a new data point.

Within the event listener, I create a new Google Maps marker with a position set to the latitude and longitude of the click event.

Optionally, you can create a new info window associated with each new point that opens upon creation. I also created a blank ‘div’ element as placeholder content within the info window.

Within the event listener, I also created a form that allows for user input associated with each new point when stored in the backend database. The form includes a series of input fields to collect the relevant point information, stored as innerHTML.

Additionally, I created a form submit button with a click event that triggers a subsequent “getFormData” function on click (discussed later). I then appended both the form and submit button to the ‘div’ element contained as content within each new info window.

On double click and creation of a new point, an info window complete with the aforementioned form and submit button should open and allow for user input.

Upon submission of the info window form, I needed to collect the data input by the user for use in later methods. I did this by calling a “getFormData” function that utilized the JavaScript FormData constructor to retrieve each user input and store it to a variable.

“getFormData” calls on an additional function, “addNewPoint,” which receives the user input data and triggers an HTTP POST request to the established API and adds a new entry to the backend database.

This function submits the serialized user data to the API and parses the resulting promise as JSON. I then pass the resulting data to an additional function, “renderPointCard,” which creates additional styling and click functionality on the new point data but is outside the scope of this post.

Upon refreshing the page, newly created points should persist on the page.

Creating New Polygon Data

The Google Maps JavaScript API has a built-in feature, Drawing Manager, that allows a user to easily draw new polygons (or circles, rectangles, etc.) on a map. I created a new Drawing Manager instance inside of my “initMap” function, set the position of the polygon selector button to the bottom center of the map, and customized the styling of polygon presentation.

As I described above for creating a new data point, I similarly created a map-level event listener that is triggered by the completion of a Drawing Manager polygon.

Upon completion, the polygon’s data are passed through a larger function that identifies the latitudes and longitudes of each polygon vertex. I accomplished this by using the Google Maps API’s built-in “getPaths()” method to identify an object of all latLngs that comprise the polygon and storing the resulting values to a variable. The polygon feature is a nested object that requires some drilling to identify individual latitudes and longitudes (note the .g chains below). Using a for-loop, I then separated individual latitudes and longitudes and stored them in a new array.

I followed the same process detailed above to generate an info window for each new polygon. Each of these info windows contains an editable form and submit button that triggers a method to retrieve and store the data entered into the form by the user.

In this instance, the individual latitude and longitude values for each polygon vertex are passed to the “getPolygonFormData” function via hidden form fields.

This function then passes Form Data to a subsequent function, “addNewPolygon,” which performs an HTTP POST request to the API and adds a new polygon entry to the backend database.

As with the point data methodology described above, this function submits the serialized user data to the API and parses the resulting promise as JSON. I then pass the resulting data to an additional function, “renderPolygonCard,” which creates additional styling and click functionality on the new point polygon data.

Upon refreshing the page, newly created polygons should also persist on the page.

For additional detail on how I enabled full CRUD methods on both point and polygon data using vanilla JavaScript, feel free to access my full GitHub repository, found here:

Contributions and comments are always welcome!

--

--