AngularJS 在指令运行之前通过 AJAX 检索数据 [英] AngularJS retrieve data via AJAX before Directive runs

查看:23
本文介绍了AngularJS 在指令运行之前通过 AJAX 检索数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 AngularUI 的 uiMap 指令实例化一个谷歌地图.uiMap 指令适用于硬编码数据({mapOptions}[myMarkers]);但是,当我通过 $http.get() 检索此数据时遇到了麻烦(该指令在 AJAX 调用完成之前触发).

最初我在我的 GoogleMaps 控制器中执行 GET,但是当我意识到事情发生的顺序不正确时,我将 GET 移到了 uiMap 指令中.我有两个问题:

  1. 我认为这不是正确的做法.
  2. GET 还检索 [myMarkers] 的数据
    • 创建标记的函数/指令无处不在,因为它负责创建所有覆盖

所以我的问题是,在指令运行之前,应用程序中是否还有其他地方可以检索数据(并将其应用于范围)?

我阅读了 $q,这听起来像什么我想要,但我不确定我是否可以在我的控制器中而不是在指令中完成它(也不确定 $q.defer.resolve()$ 有何不同http.success()).

编辑我使用的大部分代码是从 AngularUI 的文档中复制/粘贴的,但这里有一个 plunk:http://plnkr.co/edit/t2Nq57

解决方案

基于 Andy 的回答,我使用了 uiMap 和 uiIf:

<div ui-if="mapReady">

注意事项 1 uiIf 不能位于指定控制器提供其条件的同一元素中(uiIf 的优先级高于 ngController,因此在 uiIf 执行之前不会设置其控制器).

注意事项 2 务必使用最uiIf 的最新版本(最新标签中提供的版本 v0.3.2 已过时).旧版本在某些情况下存在导致 TypeError 的错误.

Caveat 3 jQuery 必须包含在 AngularJS 之前(在 index.html 中);否则,您将收到一个 TypeError,指出 Object [object Object] 没有方法 'trigger'(或 Object [object HTMLDivElement] 在 Windows 上没有方法 'trigger').Chrome 将允许您进入触发器函数,因为 Chrome 知道它,但 Angular 不知道(并且 Angular 正在抛出错误).

function GoogleMaps( $scope , $http ){var mapDefaults = {center: new google.maps.LatLng(25,-90),//以墨西哥湾为中心缩放: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], 缩放: 15}$scope.mapOptions = {"center": (typeof user_defaults.center !== 'undefined') ?新 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};//处理代码以填充标记对象$scope.mapReady = true;});//直接来自 http://angular-ui.github.com/#directives-map 上的示例$scope.addMarker = function($event) { ... };$scope.openMarkerInfo = function(marker) { ... };$scope.setMarkerPosition = function(marker, lat, lng) { ... };}//谷歌地图{}

缺点 uiMap 目前不支持 domready 上的渲染器.我正在研究此 GitHub 中建议的 uiMapMarker 替代版本问题/评论.
此问题的解决方案:https://stackoverflow.com/a/14617167/758177
工作示例:http://plnkr.co/edit/0CMdW3?p=preview

解决方案

你可以延迟 ui-map 的执行,直到你的数据加载完毕.

HTML:

<div ui-map="myMap" ui-options="myOpts"></div>

JS:

$http.get('/mapdata').then(function(response) {$scope.myOpts = response.data;$scope.loadingIsDone = true;});

I'm using AngularUI's uiMap directives to instantiate a google map. The uiMap directive works great with hard-coded data ({mapOptions} and [myMarkers]); however I run into trouble when I retrieve this data via $http.get() (the directive fires before the AJAX call has finished).

Initially I was executing the GET in my GoogleMaps controller, but when I realised things were happening out of sequence, I moved the GET into the uiMap directive. I've got 2 problems with this:

  1. I think this is not the correct way to do this.
  2. The GET also retrieves the data for [myMarkers]
    • The function/directive that creates the markers is ubiquitous in that it is responsible for creating all overlays

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?

I read up on $q, 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 $q.defer.resolve() is any different than $http.success()).

EDIT Most of the code I'm using is copy/paste from AngularUI's doc, but here's a plunk: http://plnkr.co/edit/t2Nq57

Solution

Based on Andy's answer, I used a combination of uiMap and uiIf:

<!-- index.html -->
<div
  id="map_container"
  ng-controller="GoogleMaps">

  <div ui-if="mapReady">

    <div
      ng-repeat="marker in markers"
      ui-map-marker="markers[$index]"
      ui-event="{'map-click':'openMarkerInfo(marker)'}"
    ></div>

    <div
      ui-map-info-window="myInfoWindow"
      ng-include="'infobox.html'"
    ></div>

    <div
      id="map_canvas"
      ui-map="myMap"
      ui-options="mapOptions"
    ></div>

  </div>

</div>

Caveat 1 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).

Caveat 2 Be sure to use the most recent version of uiIf (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.

Caveat 3 jQuery MUST be included before AngularJS (in index.html); else you will receive a TypeError stating that Object [object Object] has no method 'trigger' (or Object [object HTMLDivElement] has no method 'trigger' 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).

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{}

Drawback uiMap does not currently support rendering makers on domready. I'm looking into an alternative version of uiMapMarker suggested in this GitHub issue / comment.
Solution to this issue: https://stackoverflow.com/a/14617167/758177
Working example: http://plnkr.co/edit/0CMdW3?p=preview

解决方案

You could just delay execution of ui-map until your data is loaded.

HTML:

<div ui-if="loadingIsDone">
  <div ui-map="myMap" ui-options="myOpts"></div>
</div>

JS:

$http.get('/mapdata').then(function(response) {
  $scope.myOpts = response.data;
  $scope.loadingIsDone = true;
});

这篇关于AngularJS 在指令运行之前通过 AJAX 检索数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆