AngularJs:如何将范围从$ http.get传递到指令?

时间:2016-09-27 15:04:35

标签: angularjs asp.net-mvc angularjs-directive

我在尝试使用angular& amp;中的数据填充矢量地图时遇到了麻烦。指令。

我有一个角度仪表板网页,需要显示填充了我数据库中数据的美国svg矢量地图。我正在关注this tutorial,一切正常,但教程将硬编码值传递给地图。我需要修改它以接受数据库值,&这就是我遇到麻烦的地方。如何使用指令调用我的数据库并将这些值传递回map?

我还是刚开始接触角度和角度这是我第一次使用指令,但看起来好像$http.get调用发生在指令之后,所以我太迟了返回我的数据库数据。这是我的代码:

App.js

在这里,我正在使用这两个指令来实现此地图功能。一切正常:

var app = angular.module('dashboardApp', ['ngRoute', 'angularjs-dropdown-multiselect']);

app.controller('dashboardController', DashboardController);

app.directive('svgMap',function ($compile) {
return {
    restrict: 'A',
    templateUrl: '/Content/Images/Blank_US_Map.svg',
    link: function (scope, element, attrs) {
        var regions = element[0].querySelectorAll('path');
        angular.forEach(regions, function (path, key) {
            var regionElement = angular.element(path);
            regionElement.attr("region", "");
            regionElement.attr("dummy-data", "dummyData");
            $compile(regionElement)(scope);
        })            
    }
}
});

app.directive('region', function ($compile) {    
return {
    restrict: 'A',
    scope: {
        dummyData: "="
    },
    link: function (scope, element, attrs) {            
        scope.elementId = element.attr("id");
        scope.regionClick = function () {                
            alert(scope.dummyData[scope.elementId].value);
        };
        element.attr("ng-click", "regionClick()");
        element.attr("ng-attr-fill", "{{dummyData[elementId].value | map_color}}");
        element.removeAttr("region");
        $compile(element)(scope);
    }
}
});

DashboardController.js

这就是我的问题所在。在这里,我通过$http.get从我的数据库返回数据。我目前在此http.get&之外有我的$scope.createDummyData功能。它工作正常。但是,如果我将该代码放在$http.get中,则数据不会填充。这就是我的问题:

var DashboardController = function ($scope, $http) {
$http.get('/Account/GetDashboardDetails')
    .success(function (result) {

        //need to place my $scope.createDummyData inside here

    })
    .error(function (data) {
        console.log(data);
    });

var states = ["AL", "AK", "AS", "AZ", "AR", "CA", "CO", "CT", "DE", "DC", "FM", "FL", "GA", "GU", "HI", "ID", "IL",
        "IN", "IA", "KS", "KY", "LA", "ME", "MH", "MD", "MA", "MI", "MN", "MS", "MO", "MT", "NE", "NV", "NH", "NJ", "NM",
        "NY", "NC", "ND", "MP", "OH", "OK", "OR", "PW", "PA", "PR", "RI", "SC", "SD", "TN", "TX", "UT", "VT", "VI", "VA",
        "WA", "WV", "WI", "WY"];
$scope.createDummyData = function () {
    var dataTemp = {};
    angular.forEach(states, function (state, key) {
        dataTemp[state] = { value: Math.random() }
    });
    $scope.dummyData = dataTemp;
};
$scope.createDummyData();
};

HTML

最后,这是我的HTML。我觉得这里没有任何关于我的问题,但无论如何我都把它包括在内,以防万一:

<div class="container">
    <div svg-map class="col-md-8 col-sm-12 col-xs-12" style="height:350px;"></div>
    <p>
        <button ng-click="createDummyData()" class="btn btn-block btn-default">Create Dummy Data</button>
    </p>
    <div class="regionlist">
        <div ng-repeat="(key,region) in dummyData">
            <div>{{key}}</div>
            <div>{{region.value | number}}</div>
        </div>
    </div>
</div>

如何通过数据库数据填充地图?

由于

3 个答案:

答案 0 :(得分:0)

不确定这是否正是您正在寻找的,但可能有帮助。

我会创建一个服务来获取数据(我假设HTTP到/ Account / GetDashboardDetails返回状态列表)然后调用控制器中的服务。一旦调用完成,您就可以调用create dummyDataFunction。

// Service

angular
  .module('dashboardApp')
  .service('$dataService', dataService);

dataService.$inject = ['$http']

function dataService() {

  var service = {

    getData : getData

  }

  return service;

  //////////

  function getData() {
    return $http.get('/Account/GetDashboardDetails')
    .then(function (result) {
      return result;
    },function(error) {
      return error;
    })
  }

}  


// Controller

var DashboardController = function ($scope,$dataService) {

  $scope.dummyData = [];
  activate();

  /////////

  function activate() {
    $dataService.getData()
      .then(function(states){

        var dataTemp = {};

        angular.forEach(states, function (state, key) {
          dataTemp[state] = { value: Math.random() }
        });

        $scope.dummyData = dataTemp;

      },function(error) {
        console.log(error);
      });
  }

};

答案 1 :(得分:0)

指令的链接功能在$http.get XHR收到响应之前执行。一种方法是使用$watch等待数据:

app.directive('region', function ($compile) {    
    return {
        restrict: 'A',
        scope: {
            dummyData: "="
        },
        link: function (scope, element, attrs) {            
            scope.elementId = element.attr("id");
            scope.regionClick = function () {                
                alert(scope.dummyData[scope.elementId].value);
            };
            element.attr("ng-click", "regionClick()");
            element.attr("ng-attr-fill", "{{dummyData[elementId].value | map_color}}");
            element.removeAttr("region");
            //Use $watch to wait for data
            scope.$watch("::dummyData", function(value) {
                if (value) {
                    $compile(element)(scope);
                };
            });
        }
    }
});

在上面的示例中,监视表达式使用one-time binding,因此$compile语句只执行一次。如果想要在每次数据更改时重新编译元素,它就会变得更加复杂。

有关$watch的详情,请参阅AngularJS $rootscope.Scope API Reference - $watch

答案 2 :(得分:0)

在发出HTTP get请求之前,如果link指令的svgMap函数被调用,则无关紧要。

你所拥有的是svgMap指令动态创建region指令,这些指令从外部控制器范围绑定到dummyData

  

绑定dummyData意味着Angular已经为绑定属性注册了观察者。从字面上看,这也意味着即使在其他地方(即父控制器)的范围内实际设置了属性之前,这种绑定仍然存在。

我怀疑$scope.dummyData没有正确地从服务器分配返回的数据。

根据您问题中的代码,您在success请求上调用get处理程序并将响应返回到result变量中。但是,您没有提到如何从响应中获取数据。所以,我认为您可能会将.then()回调的响应与success()回调混淆:

如果是.success()回调:

$http.get('/Account/GetDashboardDetails')
.success(function (result) {
    $scope.dummyData = result // data exists in the `result` itself
})

如果.then()成功回调:

$http.get('/Account/GetDashboardDetails')
.then(function (response) {
    $scope.dummyData = response.data; // data is wrapped in `data`
})

如果上述情况并非如此,并且您确定已将来自服务器的返回数据正确分配给作用域,则尝试将该部分逻辑包装在$timeout()中。这会触发$scope.$apply()并确保$scope.dummyData中的更改在视图中正确反映。

var DashboardController = function ($scope, $http, $timeout) {
$http.get('/Account/GetDashboardDetails')
.success(function (result) {
   $timeout(function(){
      /* Do something here */
      $scope.dummyData = result;
   });
})