我正在尝试编写绘制条形图的指令,我希望每次数据更改时重绘图表。我目前有这个:
/* 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的所有函数中,无论何时更改任何内容,都会增加一个名为“version”的属性,这就是我希望$ watch查看的内容。
在我的模板中,我有一个带有ng-click的按钮,它调用了hideBenchmark函数。调用此函数,更新dataTable版本,但无论我尝试什么,手表都不会被触发。
我尝试在我的hideBenchmark函数中调用$ scope。$ appy()/ $ scope。$ digest(),尝试在手表中添加'true'(寻找对象不等),试着看'attrs.data' ,'data.version'并没有一个似乎触发手表!我知道我可以在范围上独立于这个数据创建另一个变量,观察并在每次更改数据时更改它,但这看起来很丑陋和不必要。
有人知道为什么不会触发手表,以及如何让它做我想做的事情?
此致
莱纳斯
答案 0 :(得分:2)
正如Sunil所建议的那样,你应该把它放在范围内:
scope: {
data: '='
}
因为如果不这样做,数据不会在指令中更新。
这里的小提琴: http://jsfiddle.net/0t4z02yw/2/
答案 1 :(得分:0)
我认为你将函数调用传递给$ watch,我认为它应该是一个引用或声明。
scope.$watch(function(){
return data.getVersion();
}, function(){
$timeout(drawChart, 500)
});
显然,应该在该上下文中定义drawChart
以使其正常工作...您可以尝试查看是否正在触发$ watcher正在记录版本的值。
scope.$watch(function(){
return data.getVersion();
}, function(v){
console.log(v)
});
注意:对于所有其他回复,说您需要将其添加到范围,这是错误的。您不需要这样做,因为您已将自己的自定义功能传递给$ watcher。您获取数据的方式'使用$parse
服务,元素很好。
答案 2 :(得分:0)
它当前不起作用的原因是因为没有任何东西使外部范围(控制器)通知内部范围(指令)它应该消化 - 这是已经改变的东西。
发生这种情况是因为数据对象不是指令范围的一部分。
处理它的几种方法:
首先,您可以将数据对象传递给指令并创建一个隔离的范围:
scope: {data: '='}
或者您可以传递一个函数指针,以便在您的情况下更改数据(hideBenchmark)时收到通知:
scope: {hideBenchmark: '@'}
Here是第一种方法的掠夺者。