我有一个链接到d3-cloud
指令且完美运行的控制器(下面的代码)。数据被添加到控制器中并传递给指令。
myApp.controller('DownloadsCloudCtrl', ['$scope',
'$rootScope',
'requestService',
'$cookieStore',
function($scope, $rootScope, requestService, $cookieStore){
$scope.d3Data = [
{
'kword': 'a',
'count': 141658,
},{
'kword': 'b',
'count': 105465,
}
];
}]);
现在,我试图通过将控制器切换到以下代码来从JSON请求服务中提取数据。当我在
console.log
行下面的控制器中执行$scope.d3Data = data
时,一切似乎都正常工作(返回了正确的数据)。但是,尝试将控制器链接到指令时,由于某些原因,指令获取的是未定义/空数据集,所以某些操作会中断。
我想知道问题是否在代码执行的顺序上。也许控制器尝试在JSON服务完成之前将数据传递给指令,从而导致未绘制任何图形。这可能发生吗,如果是这样,我该如何解决呢?
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'));
}]);
编辑:指令代码:
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代码:(足够简单)
<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>
最佳答案
尝试在$ scope.d3Data = data之后添加$ scope。$ apply();
$scope.d3Data = data;
$scope.$apply();
如果这不起作用,则始终可以将函数向下传递给指令,并将其设置为更新数据,然后从控制器手动调用它:
所以控制器逻辑:
$scope.updateDirective = function () {}; // this will be overridden in directive
指令逻辑:
scope: {
data: '=',
update: '&updateDirective'
label: '@'
}
scope.updateDirective = function () {
scope.render(scope.data); // call to update function
};
标记:
<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>