-->

Angular + D3 - Get scope values to show in templat

2019-06-07 19:37发布

问题:

I'm working on a map application using D3 and Angular, and I'm having an issue showing scope values in a template from an on-click event.

My directive:

angular.module("maineMap")
    .directive("ngMap", ["appConfig", function(config){

        function countyClickHandler(d, i, scope){
            scope.currentCounty(d.properties.fips);
                console.log(scope.countySelection);
        }

        function initMap() {

            //.... other code

            g.append("g")
            .attr("class", "counties")
            .selectAll("path")
            .data(scope.mapData.features)
            .enter()
            .append("path")
            .attr("d", path)
            .attr("class", function(d){
                return d.properties.name;
            })
            .on("click", function(d, i){
                countyClickHandler(d, i, scope);
            });

        }

        return {
            restrict : "E",
            link : function(scope, el, attrs){
                initMap(scope, el);
            }
        };
    }]);

My controller:

angular.module("maineMap")
.controller('MapCtrl', ['$scope','MapService', function($scope, MapService){
    //execute data fetches via promises on template load
    $scope.mapData = MapService.getMapPaths().getData();
    $scope.cityData = MapService.getCityPositions().getData();
    $scope.countyData = MapService.getMapData().getData();

    $scope.countySelection = {};
    $scope.currentCounty = function(fips){
        $scope.countySelection = getCountyData($scope, fips);
        console.log($scope.countySelection);
    };

}]);

//helper function to extract data from external JSON file
function getCountyData($scope, fips){
    for(var i = 0; i < $scope.countyData.properties.length; i++) {
        if ($scope.countyData.properties[i].FIPS === fips){
            return $scope.countyData.properties[i];
        }
    }
}

So, current behavior has an click event bound to the paths drawn within the directive. The controller has a function bound to the scope which executes the helper function to get the relevant data.

The console.log() statements print out as expected, with the controller method showing first, then the directive call second. So I know these values are visible on the scope. However, with this template, they are not showing at all:

<ng-map>
    <div id = "countyData">
        County: <span class = "countyDataPoint"> {{countySelection}}</span>
        2000 Population: <span class = "countyDataPoint"> {{countySelection.POP2000}}</span>
    </div>
</ng-map>

The only output from the countyData div is a pair of empty {} for the County element. countySelection.POP2000 is empty.

Given this layout, how can I have the template update with the scope values via a click event`?

回答1:

Solution was to use an $apply within the click handler:

function countyClickHandler(d, i, scope){
        scope.$apply(function(){
            scope.currentCounty(d.properties.fips);
        });
}