title: AngularJS retrieve data via AJAX before Directive runs
body: <p>I'm using AngularUI's <strong><a href="http://angular-ui.github.com/#directives-map" rel="nofollow noreferrer">uiMap</a></strong> directives to instantiate a google map. The uiMap directive works great with hard-coded data (<code>{mapOptions}</code> and <code>[myMarkers]</code>); however I run into trouble when I retrieve this data via <code>$http.get()</code> (the directive fires before the AJAX call has finished).</p>
  
  <p>Initially I was executing the GET in my <code>GoogleMaps</code> controller, but when I realised things were happening out of sequence, I moved the GET into the <code>uiMap</code> directive. I've got 2 problems with this:</p>
  
  <ol>
  <li>I think this is not the correct way to do this.</li>
  <li>The GET also retrieves the data for <code>[myMarkers]</code>
  <ul><li>The function/directive that creates the markers is ubiquitous in that it is responsible for creating all <i>overlays</i></li></ul>
  </li>
  </ol>
  
  <p>So my question is, is there somewhere else in the application where I can retrieve the data (and apply it to scope) before the directive runs?</p>
  
  <p>I read up on <a href="http://docs.angularjs.org/api/ng.$q" rel="nofollow noreferrer">$q</a>, and that kind of sounds like what I want, but I'm not sure if I can do it within my controller rather than in the directive (also not sure how <code>$q.defer.resolve()</code> is any different than <code>$http.success()</code>).</p>
  
  <p><strong>EDIT</strong> Most of the code I'm using is copy/paste from AngularUI's doc, but here's a plunk: <a href="http://plnkr.co/edit/t2Nq57" rel="nofollow noreferrer">http://plnkr.co/edit/t2Nq57</a></p>
  
  <h1>Solution</h1>
  
  <p>Based on <a href="https://stackoverflow.com/a/14528733/758177">Andy's answer</a>, I used a combination of uiMap and <strong><a href="http://angular-ui.github.com/#directives-if" rel="nofollow noreferrer">uiIf</a></strong>:</p>
  
  <pre><code>&lt;!-- index.html --&gt;
  &lt;div
    id="map_container"
    ng-controller="GoogleMaps"&gt;
  
    &lt;div ui-if="mapReady"&gt;
  
      &lt;div
        ng-repeat="marker in markers"
        ui-map-marker="markers[$index]"
        ui-event="{'map-click':'openMarkerInfo(marker)'}"
      &gt;&lt;/div&gt;
  
      &lt;div
        ui-map-info-window="myInfoWindow"
        ng-include="'infobox.html'"
      &gt;&lt;/div&gt;
  
      &lt;div
        id="map_canvas"
        ui-map="myMap"
        ui-options="mapOptions"
      &gt;&lt;/div&gt;
  
    &lt;/div&gt;
  
  &lt;/div&gt;
  </code></pre>
  
  <p><strong>Caveat 1</strong> uiIf cannot be in the same element that specifies the controller furnishing its condition (uiIf has higher priority than ngController, so its controller won't get set before uiIf executes).</p>
  
  <p><strong>Caveat 2</strong> Be sure to use the most <a href="https://github.com/angular-ui/angular-ui/blob/master/modules/directives/if/if.js" rel="nofollow noreferrer">recent version of uiIf</a> (the version supplied in the most recent tag, v0.3.2, is out of date). The old one has bug causing a TypeError under certain circumstances.</p>
  
  <p><strong>Caveat 3</strong> jQuery MUST be included before AngularJS (in index.html); else you will receive a TypeError stating that <code>Object [object Object] has no method 'trigger'</code> (or <code>Object [object HTMLDivElement] has no method 'trigger'</code> on Windows). Chrome will allow you to step into the trigger function because Chrome knows about it, but Angular does not (and Angular is throwing the error).</p>
  
  <pre><code>function GoogleMaps( $scope , $http )
  {
  
    var mapDefaults = {
      center:    new google.maps.LatLng(25,-90),//centres on Gulf of Mexico
      zoom:      4,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    };
  
    $scope.mapOptions = {};
    $scope.mapReady = false;
    $scope.markers = [];
  
    $http.get('map.json').then(function mapData(response) {
  
      var map_data = response.data,
        user_defaults = map_data.user.defaults; //{center: [lat,lng], zoom: 15}
  
      $scope.mapOptions = {
        "center":    (typeof user_defaults.center !== 'undefined') ?
          new google.maps.LatLng(user_defaults.center[0],user_defaults.center[1])
          : mapDefaults.center,
        "zoom":      (typeof user_defaults.zoom !== 'undefined') ?
          parseInt(user_defaults.zoom,10)
          : mapDefaults.zoom,
        "mapTypeId": mapDefaults.mapTypeId
      };
  
      //working on code to populate markers object
  
      $scope.mapReady = true;
  
    });
  
    // straight from sample on http://angular-ui.github.com/#directives-map
    $scope.addMarker = function($event) { … };
    $scope.openMarkerInfo = function(marker) { … };
    $scope.setMarkerPosition = function(marker, lat, lng) { … };
  
  }//GoogleMaps{}
  </code></pre>
  
  <p><s><strong>Drawback</strong> uiMap does not currently support rendering makers on domready. I'm looking into an alternative version of uiMapMarker suggested in this <a href="https://github.com/angular-ui/angular-ui/issues/173#issuecomment-8765849" rel="nofollow noreferrer">GitHub issue / comment</a>.</s>
  <br />Solution to this issue: <a href="https://stackoverflow.com/a/14617167/758177">https://stackoverflow.com/a/14617167/758177</a>
  <br />Working example: <a href="http://plnkr.co/edit/0CMdW3?p=preview" rel="nofollow noreferrer">http://plnkr.co/edit/0CMdW3?p=preview</a></p>