EmberJS with Google Maps - Feedback requested

##Introduction

I’m trying to get a better understanding of EmberJS by creating a project using Google Maps. I’ve published a sample on https://github.com/ddewaele/my-emberjs-starter-kit/tree/master/google-maps and I would love to get some feedback on the implementation.

Requirements

The app has the following requirements (currently implemented) :

  • App needs to be able to display a map
  • User can click on the map, causing a marker to be added on the map and in a table below the map.
  • User can add multiple markers like this
  • User can highlight on or more markers by clicking on them, or by selecting them from the table below the map.
  • User can remove the highlighted markers.

The app looks like this: http://quick.as/864ijp

I would love to get some feedback on the design of the app, and where I totally went wrong :smile:

High level design

  • Custom Ember View

A custom Ember View that inserts a DIV where the map will be displayed. We store a reference to the Google Map on the view We also store a collection of markers on the map. Handles adding / selecting markers

  • ArrayController for marker management

An ArrayController to do the marker management. (capable of working with multiple markers) Responsible for managing adding / deleting / selecting markers.

  • ObjectController, acting as a proxy to my marker object.

  • Marker Model should model the data (lat/lng)

Issues / doubts

I do however have a couple of issues / doubts regarding the design of the app :

  • View / Controller coupling

Currently the Ember View has a dependency on the “current” controller. So this means that the View can only be used when this particular controller is active.

  • View responsibility

The Ember View registers the Google Maps listeners (clicking on the map) in the didInsertElement. It also adds a google.maps.Marker to the map and adds a App.Marker (a wrapper for the google.maps.Marker) to the controller. When a marker is clicked on the map, the controller processes the logic. (markerClick)

So the view handles all the interaction with the map (clicking on the map to add a marker, and clicking on a marker to highlight it) by delegating the processing to the controller.

  • Marker Model

My marker object doesn’t extend Ember.Model,just Ember.Object. If we’re not persisting I guess this is ok ?

  • Controller state

When a marker is added to the map (by clicking on the map), the View delegates that to the controller, where the controller stores it in an internal array.

  • View state. When clicking on a marker, the View again delegates it to the Controller, allowing the controller to perform some logic

In order to do that, the View also needs to have a list of App.Marker objects. (as it needs to know what Marker object it needs to pass on to the controller)

-Clicking on a marker

When clicking on a marker, I’m currently toggling the selected state on the marker object itself.

markerClick: function(marker) { marker.set(“selected”,!marker.get(“selected”)); },

I’d much rather not pollute my object with the selected state but use an itemController. However, when setting an itemController:“Marker” I ran into the issues that my App.MarkerController.markerIcon observer was called twice on each marker click.

I’m using my MarkerController to observe the “selected” property an set the icon on the marker accordingly.

Conclusion

If you made it this far thanks a lot ! Feel free to provide feedback here or on the Github project.

This looks pretty solid to me. Regarding your issues/doubts:

View/controller coupling – In a more complicated app you might want to use the render (http://emberjs.com/guides/templates/rendering-with-helpers/#toc_the-code-render-code-helper) but for something this simple it’s not the worst thing in the world to reference the current controller.

View responsibility – Having the view handle all of the interaction and delegating further processing to the controller seems very reasonable to me.

Marker model – As you said, you’re not persisting so you can get away with a Ember.Object here.

Controller state and view state – Seems like there’s probably a way to wrap the markers in some sort of ArrayProxy to handle the different in representation between controller and view, but the way you’ve done it seems pretty reasonable for such a simple example.

I think the best way to go with this is with an Ember component. You have to keep track of the markers/polyline etc on the view element anyway so there is actually not much you gain from ember’s controller/view seperation.

If you need bind to some controller elements you can also achieve this by a property binding directly from the template. What’s additionally useful is when you go this route you can use the ember-component in your ‘normal’ html by creating it directly from js and appending it to the dom from js.

Components = Ember.Namespace.create();
....
Components.MapComponent.create({markers: anArrayOfPoiObjects}).appendTo('#mapComponent');

I think that’s a great way to improve existing apps when one is in a transitioning phase from a ‘normal’ webpage to a single page application.

Nice work. I was working on something similar and your code help me a lot. What about the binding between the markers array and the google maps markers?

It should be great if pushing objects to the array will create a new marker on the map.

Maybe it could be done using the addArrayObserver method EmberArray - 4.6 - Ember API Documentation

Something similar to the CollectionView https://github.com/emberjs/ember.js/blob/v1.1.2/packages/ember-views/lib/views/collection_view.js#L11

I don’t know if there is an easier way of do that