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!
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.":https://gist.github.com/mustmodify/5535599 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 https://gist.github.com/mustmodify/5533979/revisions 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.
code: http://plnkr.co/edit/lEvDK8NrvR2K5Ephsy7e
References
"Writing AngularJS Services":http://stackoverflow.com/questions/13320015/how-to-write-a-debounce-service-in-angularjs
AngularJS docs
GoogleMaps AngularJS Directive
Ways to display webpages that use angularjs and multiple files
Plnkr.co -- Tthis is cool because you can (a) reference gists (a la http://plnkr.co/edit/gist:5533979?p=preview )... 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.
[bl.ocks.org](http://bl.ocks.org] 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. bl.ocks.org includes title, your output, and then your code. So a bit less useful for iframes, but great for linking. For instance, try http://bl.ocks.org/mustmodify/5533979/1e4fac2390cadc16c4bf78ba4c83ba582ad1ec6b
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
On Mapping
MapQuest Open SDK API Docs -- mostly harmless