Angular $ clock not firing

I am trying to write a directive for drawing barcards and I would like it to redraw the chart every time the data changes. I currently have this:

/* 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));

      

Then in my controller I:

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());
  }

      

In all the functions from the dataTable, whenever anything changes, a property called "version" is incremented, which is what I want to watch $ watch at.

In my template, I have an ng clicked button that calls the hideBenchmark function. This function gets called, the dataTable version is updated, but no matter what I try, the clock won't start.

I tried using $ scope. $ appy () / $ scope. $ digest () in my hideBenchmark function, tried adding "true" to the clock (looking for object inequality), tried looking at 'attrs.data', 'data.version' and none of them seem to start the clock! I know I can create another variable in scope, independent of this data, and keep track of and change it every time I change data, but that seems ugly and unnecessary.

Does anyone know WHY the clock is not firing and how can I get it to do what I want?

Hello,

Linus

+3


source to share


3 answers


As suggested by Sunil, you should place it in the scope:

scope: {
    data: '='
} 

      



Because if you don't, the data will not be updated in the directive.

Here's a fiddle: http://jsfiddle.net/0t4z02yw/2/

+2


source


You are passing a function call to $ watch, it should be a reference or a declaration I guess.

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

      

Obviously it drawChart

needs to be defined in this context for this to work ... what you can try to figure out if the $ watcher starts is registering the version value.



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

      

Note. For all other answers where you need to add it to scope, this is false. You don't need to do this because you are passing your own function to the $ watcher function. The way you get your "item" is great with a service $parse

.

0


source


the reason it is currently not working is that nothing makes the outer scope (controller) notifying the inner scope (directive) that it should digest is what has changed. This is because the data object is not part of the scope. A couple of ways to deal with this:
First, you can pass a data object to a directive and create an isolated scope:

scope: {data: '='}

      

Or you can pass a function pointer to notify when data has changed (hideBenchmark) in your case:

scope: {hideBenchmark: '@'}

      

Here is the plunker for the first method.

0


source







All Articles