2016-09-27 3 views
0

У меня возникли проблемы с попыткой заполнить векторную карту из данных моей базы данных, используя угловые директивы &.

У меня есть веб-страница с угловой приборной панелью, которая должна отображать векторную карту svg из Соединенных Штатов, заполненную данными из моей базы данных. Я следую this tutorial, и все работает отлично, однако учебник передает жестко закодированные значения на карту. Мне нужно изменить это, чтобы принимать значения базы данных, &, вот где у меня проблемы. Как я могу позвонить в мою базу данных и передать эти значения обратно на карту, используя директиву?

Я еще не знаком с угловым & Это мой первый опыт работы с директивами, но кажется, что после директивы появляется $http.get, поэтому я возвращаю данные db слишком поздно. Вот мой код:

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. В настоящее время у меня есть моя функция $scope.createDummyData за пределами этого http.get &, она отлично работает. Однако, если я размещаю этот код внутри своего $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> 

Как я могу идти о заселении моей карты, с помощью информации из базы данных?

Благодаря

+0

Почему вы не вызываете HTTP-вызов из директивы? – user2085143

+1

Попробуйте обернуть ng-if вокруг div, содержащего svg-map. Первоначально установите для переменной ng-if значение false, а затем, как только вы получите данные из бэкэнд и заполните dummydata, установите для параметра ng-if значение true. Это начнет отображать ваш шаблон. –

+0

Вы только показали, как назначить фиктивные данные в '$ scope' в методе' createDummyData'. _Как вы реализуете ту же логику для данных, возвращаемых с сервера? _ –

ответ

0

Не уверен, если это то, что вы ищете точно, но может помочь.

Я бы создал службу для захвата данных (я предполагаю, что HTTP to/Account/GetDashboardDetails возвращает список состояний), а затем вызовите службу в контроллере. Как только вызов будет завершен, вы затем вызываете свой созданный 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); 
     }); 
    } 

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

0

Это не имеет значения, если link функция вашей svgMap директивы называется путь, прежде чем вы когда-либо сделать HTTP GET запрос.

У вас есть то, что директива svgMap динамически создает директивы region, которые привязаны к dummyData из области внешнего контроллера.

Будучи связан к dummyData означает Угловой уже зарегистрированы наблюдатели для связанного имущества. Буквально это также означает, что это связывание существует еще до того, как свойства действительно установлены в области в другом месте, то есть в родительском контроллере.

Я подозреваю, что $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; 
    }); 
}) 
Смежные вопросы