2014-11-04 156 views
3

我正在嘗試寫一個指令來繪製barcharts,並且我希望它在每次數據更改時重繪圖表。目前,我有這樣的:

/* This directive will create a bar chart based on a dataTable. 
* It expects the first column of the data table to contain the labels. 
* If more than 2 columns (labels plus more than one value) are supplied, 
* all bars generated by values in one row will be grouped together, making 
* an easy visual comparison (benchmark). 
* If the option overlay is supplied, the odd value columns will be drawn 
* underneath the even values (Ex [label, col1, col2, col3, col4], with overlay = true will result 
* in col1 and col3 to be drawn underneath col2 and col4 
*/ 


angular.module('kapstok').directive('nBarChart', ['$window', '$location', '$parse', '$timeout', 
    function($window, $location, $parse, $timeout){ 
    return{ 
    restrict: 'E', 
    scope: true, 
    link: function(scope, elm, attrs){ 

     // Read all the different parameters givin in the directive declaration. 
     // If options are not given, they are replaced by their default values. 
     var dataGetter  = $parse(attrs.data); 
     var data = dataGetter(scope) || undefined; 
     if(!data){ 
     throw Error("No (valid) data source specified!"); 
     } 



      // Redraw the table once the table gets updated. However, usually multiple elements 
     // of the table will be updated at the same time, while the watch will get triggered 
     // at each update. To prevent this, we give it a timeout of half a second, 
     // allowing all the updates to be applied before the table is redrawn. 
     scope.$watch(function(){ return data.getVersion(); }, $timeout(drawChart, 500)); 

然後,在我的控制我做的:

controlmodule.controller('PrefscanController',['$http', '$scope', 'DataTable', function($http, $scope, DataTable){ 
    $scope.myData = new DataTable(); 
    $scope.myData.addColumn("string", "label"); 
    $scope.myData.addColumn("number", "survey"); 
    $scope.myData.addColumn("number", "benchmark"); 
    $scope.myData.addColumn("number", "break-it"); 

    $scope.myData.addRow(['test', 20, 10, 4]); 
    $scope.myData.addRow(['test2', 42, 13, 2]); 


    $scope.hideBenchmark = function(){ 
    console.log("myData.version = ", $scope.myData.getVersion()); 
    $scope.myData.hideColumn(2); 
    console.log("myData.version = ", $scope.myData.getVersion()); 
    } 

從dataTable中,一旦有事情發生變化的所謂「版本」屬性增加,所有的功能是什麼我想要$手錶看看。

在我的模板中,我有一個帶有ng-click的按鈕,它調用hideBenchmark函數。這個函數確實被調用,dataTable版本被更新,但無論我嘗試什麼,手錶都不會被觸發。我試過在我的hideBenchmark函數中添加'true'(尋找對象的不等式),試着看'attrs.data()/ $ scope。$ digest() ','data.version',它們都沒有觸發手錶!我知道我可以在獨立於該數據的範圍上創建另一個變量,觀察並在每次更改數據時都進行更改,但看起來很醜陋,沒有必要。

有人知道爲什麼手錶沒有被觸發,我怎麼能做到我想要的?

問候,

萊納斯

+0

您是否嘗試將「數據」放在您的指令範圍內,而不是將其從屬性中取出? – 2014-11-04 10:46:45

回答

2

正如蘇尼爾建議,你應該把它的範圍:

scope: { 
    data: '=' 
} 

因爲如果你不這樣做,數據不更新中指示。

這裏小提琴: http://jsfiddle.net/0t4z02yw/2/

+0

非常感謝!這就是訣竅! – Linus 2014-11-04 11:23:42

0

你傳遞一個函數調用到$手錶,它應該是一個參考或聲明,我想。

scope.$watch(function(){ 
     return data.getVersion(); 
    }, function(){ 
     $timeout(drawChart, 500) 
    }); 

顯然,drawChart應該在這方面進行定義這個工作......你可以嘗試看看是否$觀察者被觸發時記錄的版本價值。

scope.$watch(function(){ 
     return data.getVersion(); 
    }, function(v){ 
     console.log(v) 
    }); 

注意:對於所有其他回覆說您需要將其添加到範圍,這是錯誤的。您不需要這麼做,因爲您將自己的自定義函數傳遞給$ watcher。通過$parse服務獲得'data'元素的方式很好。

0

它目前沒有工作的原因是因爲沒有任何東西使得外部範圍(控制器)通知它應該消化的內部範圍(指令) - 這已經被改變了。 發生這種情況是因爲數據對象不是指令作用域的一部分。 幾個方法來對付它:
首先,你可以傳遞數據對象的指令,然後創建一個孤立的範圍:

scope: {data: '='} 

或者你可以傳遞一個函數指針被通知當數據發生變化( hideBenchmark)你的情況:

scope: {hideBenchmark: '@'} 

Here是第一個方法plunker。