2014-10-03 3 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

+0

Это не похоже на хороший дизайн. Директива должна иметь возможность обрабатывать значения «undefined» и не должна допускать каких-либо предположений о том, что у родительской области есть или нет. –

+0

Его приложение D3, которое требует данных для рисования путей SVG. – Jason

0

Я использовал joakimbi's решение этой проблемы. В частности, я добавил зависимость ngRoute и использовал свойство resolve, чтобы гарантировать, что вложенные обещания будут выполнять выборку данных до отображения представления.

Обновленный сервис:

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() { ... } 
    }; 
}]); 

Модифицированный приложение инициализатор, который определяет перспективы в собственности постановляю:

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 было подходящим решением.

Смежные вопросы