2014-10-03 36 views
1

基本上,我有兩條指令:如何將資源調用與指令集成?

angular.module("maineMap") 
.directive("ngMap", ["APPCONFIG", "Map", function(config, Map){ 
     //D3 map drawing functionality based on data from $resource call 
     return { 
     restrict : "E", 
     transclude : true, 
     scope : { 
      mapData : '=' 
     }, 
     link : function(scope, el, attrs){ 
        } 
     }; 
    }]) 
    .directive("donutChart", function(){ 
    return { 
     restrict : "E", 
     link : function(scope, el, attrs){ 
        } 
      } 
    }); 

和控制器

angular.module("maineMap") 
.controller('MapCtrl', ['$scope','Map', function($scope, Map{ 
    $scope.mapData = Map.mapData() 
         .query(); 

    $scope.mapData.$promise.then(function(results){ 
     $scope.mapData = results; 
     console.log($scope.mapData); 
    }); 

}]); 

其中Map$resource實現獲得JSON文件。

我的問題是指令功能在控制器調用之前執行。也就是說,我在指令中調用mapData的幾個屬性,它們都在控制檯中返回未定義的相應錯誤消息。但是,錯誤打印輸出後不久,從$resource執行的數據獲取將執行並打印到控制檯。

需要注意的是,如果我更換$promise並只對

$scope.mapData = Map.mapData() 
         .query(); 

取決於那我$scope.mapData可見的<donut-chart>指令,但不<ng-map>

鑑於這種結構,我怎麼才能延遲指令功能,直到控制器加載數據之後?

回答

0

執行用於順序:

<div ng-controller="controller"> 
    <outer> 
     <inner></inner> 
     <inner></inner> 
    </outer> 
</div> 

將是:

  1. 編譯(內)
  2. 編譯(內)
  3. 編譯(外)
  4. 控制器
  5. 控制器(外部)
  6. 控制器(內)
  7. 鏈路(內)
  8. 控制器(內)
  9. 鏈路(內)
  10. 鏈路(外)

所以,控制器明確規定的範圍的連接之前指令發生。當然,除非範圍設置在異步函數中。但是你的指令應該能夠處理undefined範圍值,因爲該指令沒有(可能不應該)關心它在哪個控制器下運行,除非它是requires它。

+0

多數民衆贊成在事情..範圍值設置在一個異步功能和獲取的數據是不可或缺的指令。如果該指令沒有數據,則會引發錯誤並且不執行任何操作。 – Jason 2014-10-03 21:30:04

+0

這看起來不是一個好設計。一個指令應該能夠處理未定義的值,並且不應該對於父範圍有或沒有做出任何假設。 – 2014-10-03 22:29:43

+0

它是D3應用程序,它需要數據來繪製svg路徑。 – Jason 2014-10-03 22:30:36

0

我對此問題使用了joakimbi's解決方案。具體而言,我添加了ngRoute依賴項,並使用resolve屬性確保封閉的promise將在顯示視圖之前執行數據提取。

更新服務:

angular.module("maineMap") 
.factory("MapService", ["$http", "$log", "$q", "appConfig", function($http, $log, $q, appConfig){ 
    var mapPaths, mapPromise, 
     cityPositions, cityPromise; 

    return { 
     getMapPaths : function(){ 

      mapPromise = $http.get(appConfig.maineData) 
           .success(function(data){ 
            mapPaths = data; 
           }); 

      return { 
       getData : function(){ 
        return mapPaths; 
       }, 
       setData : function(data){ 
        mapPaths = data; 
       }, 
       promise : mapPromise 
      }; 
     }, 
     getCityPositions : function() { ... } 
    }; 
}]); 

改性應用初始化限定在resolve屬性的承諾:

angular.module("maineMap", ["ngResource", "ngRoute", "configuration"]) 
.config(["$routeProvider", function($routeProvider){ 
    $routeProvider.when("/", { 
     templateUrl : "views/main.html", 
     controller : "MapCtrl", 
     resolve : { 
      "MapData" : function(MapService){ 
       return MapService.getMapPaths().promise; 
      }, 
      "CityData" : function(MapService){ 
       return MapService.getCityPositions().promise; 
      } 
     } 
    }); 
}]); 

修改的控制器,其中所述數據讀取之前的視圖加載:

angular.module("maineMap") 
.controller('MapCtrl', ['$scope','MapService', function($scope, MapService){ 
    $scope.mapData = MapService.getMapPaths().getData(); 
    $scope.cityData = MapService.getCityPositions().getData(); 
    $scope.currentCounty = {}; 
    console.log("MapData: " + $scope.mapData); 
}]); 

這樣做的結果是,在指令的標記被處理之前d在視圖模板中,數據獲取會執行並將結果保存在範圍中,從而使其可用於指令。

Martin Atkins提出的另一種選擇是將數據加載到變量angular.constant()中。由於我打算擴展這個應用程序的幾個意見,ngRoute結合resolve承諾是適當的解決方案。