Reputation: 5409
I have a controller (code below) that links to a d3-cloud
directive and works perfectly. Data is added in the controller and passed to the directive.
myApp.controller('DownloadsCloudCtrl', ['$scope',
'$rootScope',
'requestService',
'$cookieStore',
function($scope, $rootScope, requestService, $cookieStore){
$scope.d3Data = [
{
'kword': 'a',
'count': 141658,
},{
'kword': 'b',
'count': 105465,
}
];
}]);
Now I'm trying to pull data from a JSON request service by switching my controller to the following code. When I do a console.log
in the controller underneath the $scope.d3Data = data
line, everything appears to be working properly (the proper data is returned).
However, something breaks when trying to link the controller to the directive, for some reason the directive is getting an undefined/null data set.
I'm wondering if the issue is in the order with which the code executes. Perhaps the controller tries to pass data to the directive before the JSON service has finished, thus resulting in no graph being drawn. Could this be happening, and if so, how can I go about fixing it?
myApp.controller('DownloadsCloudCtrl', ['$scope',
'$rootScope',
'requestService',
'$cookieStore',
function($scope, $rootScope, requestService, $cookieStore){
$rootScope.$on('updateDashboard', function(event, month, year) {
updateDashboard(month, year);
});
var updateDashboard = function(month, year) {
requestService.getP2PKeywordData(month, year).then(function(data) {
$scope.d3Data = data;
});
};
updateDashboard($cookieStore.get('month'), $cookieStore.get('year'));
}]);
EDIT: Directive code:
myApp.directive('d3Cloud', ['$window',
'd3Service',
'd3Cloud',
function($window,
d3Service,
d3Cloud) {
return {
// Restrict usage to element/attribute
restrict: 'EA',
// Manage scope properties
scope: {
// Bi-directional data binding
data: '=',
// Bind to DOM attribute
label: '@'
},
// Link to DOM
link: function(scope, element, attrs) {
// Load d3 service
d3Service.d3().then(function(d3) {
// Re-render on window resize
window.onresize = function() {
scope.$apply();
};
// Call render function on window resize
scope.$watch(function() {
return angular.element($window)[0].innerWidth;
}, function() {
scope.render(scope.data);
});
// Render d3 chart
scope.render = function(data) {
// d3 specific appends... not important
HTML Code: (simple enough)
<div class="col-md-6">
<div class="module">
<div class="inner-module" ng-controller="DownloadsCloudCtrl">
<div class="module-graph">
<d3-cloud data="d3Data"></d3-cloud>
</div>
</div>
</div>
</div>
Upvotes: 1
Views: 54
Reputation: 2510
try adding a $scope.$apply() after $scope.d3Data = data;
$scope.d3Data = data;
$scope.$apply();
if this doesn't work, you can always pass a function down into the directive and set it to update the data and then manually call it from the controller:
so controller logic:
$scope.updateDirective = function () {}; // this will be overridden in directive
directive logic:
scope: {
data: '=',
update: '&updateDirective'
label: '@'
}
scope.updateDirective = function () {
scope.render(scope.data); // call to update function
};
markup:
<div class="col-md-6">
<div class="module">
<div class="inner-module" ng-controller="DownloadsCloudCtrl">
<div class="module-graph">
<d3-cloud data="d3Data" update-directive="updateDirective"></d3-cloud>
</div>
</div>
</div>
</div>
Upvotes: 1