MapQuest and AngularJS

By: Johnathon Wright on: May 07, 2013

For my current project, I need to show MapQuest maps next to an address form. As the user enters an address, I need the map to attempt to show the address.

Note: When testing, I often use console.log... so if you don't have developer tools installed, some of these won't work for you.

Step One: Basic Gist

Using this basic angularjs gist as a starting place, I added the basic code from MapQuest's open data API. It works!

Source Outcome

Step Two: using AngularJS templates ( the single-page-app thing )

In this case, you can see that the angular app is active... the word "World" replaces {{name}}. Importantly, though the content here is generated on the server side, not the client side. In my project, the map must be rendered by angularjs on the client side as part of a "single-page-app." This has something to do with HTML5 and hashtag-urls. I'm still not totally comfortable with these concepts yet, but I have seen their coolness and am getting there.

Steps to transition this from server-side to client-side rendering: * Move the content to a template file (map.html) * create a router that will recognize the current location and pick the right template to render * add

or equivalent on the server side so Angular knows where to place its content.

Here are the changes:


Not surprisingly, the map disappears. Note this line of javascript:

  MQA.EventUtil.observe(window, 'load', function() {

so the map is drawn on window load. And angular is still loading so the #map div isn't available at that time. You can tell that the map.html view is being rendered, though, because "Here is the map" acts as a canary.

Step Three: get my map back.

based on the referenced Stack Overflow pages, looks like $routeChangeSuccess might be a winner.


However, the $routeChangeSuccess event is called twice. The first time, it is unsuccessful, since there is no #map present. ( this is the redirect in the router. )

"Here's one possible fix.": It won't work once we have multiple routes, though.

Step Four: Add Address Form

Step Five: Map Address

Adding ng-model="location.zipcode" to the input tags for the form, we can then reference that data from angularjs via $scope.location.zipcode. We shouldn't bother mapping until we have at least a complete zipcode:

For diff, see revisions 676bf92 and 49f3f96

Step Six: Cartography

This is actually version 3 of our app. Previous versions integrated with MapQuest with heavy-handed jQuery. Instead of reusing that code I'm investing time in getting a MapQuest situation working... hopefully that pays off. It's a risk, but I think a useful one.

AngularJS has Directives which, in theory, should allow me to abstract away the setup to a plugin.



"Writing AngularJS Services":

AngularJS docs



AngularJS Directives

GoogleMaps AngularJS Directive

Ways to display webpages that use angularjs and multiple files -- Tthis is cool because you can (a) reference gists (a la )... this is how the people on #angularjs ask you to present your questions so they don't have to guess what you're doing. However, you can't embed code from a gist in your blog... you must create a "plunk" and use that. Also, doesn't seem to be able to reference previous versions by commit number.

[](] allows you to render github gists based on a gist number, OR a gist number and a revision number. Uses github's URL structure.... which I guess isn't as much a feature as it gives me the impression that it's a lightweight, and by implication hopefully well-crafted and stable, layer. Plnkr's embeding doesn't add anything to the page... just shows the content from index.html. includes title, your output, and then your code. So a bit less useful for iframes, but great for linking. For instance, try

On Events

SO: AngularJS: how to run additional code after rendering a template

SO: AngularJS, how to watch for a route change

SO: AngularJS: Handling route changes

Events Not Documented

On Mapping

MapQuest Open SDK API Docs -- mostly harmless


Just checking that you are human. What would be the result of this code?

a = 3*(4/2); b = 1; a+b