2

I am using a directive that injects a service. When the data changes from the service I would like the directive to update.

I know I need to use $watch but I am not sure how to implement it in my situation.

I have tried a couple of scenarios but they have not worked. Below is my directive.

Can someone please show me how to add in the $watch so the directive updates when the data changes?

app.directive('googleAnalytics', function(configFactory){
  return {
    restrict: 'E',
    replace: true,
    link: function(scope,element,attrs){
      configFactory.getconfigs().then(function(configs) {
        scope.gid = configs[0].ga_id;
        var scriptTag = angular.element(document.createElement("script"));
          scriptTag.text("ga('create', '"+scope.gid+"', 'auto');")
          element.append(scriptTag);
      });
    }
  };
})

1 Answer 1

1

Using $watch with promises is quite problematic. I have never got it working properly so I'd suggest you use $broadcast in your service to notify listeners for any changes. Or you could easily implement your own, light weight, watcher-like behavior.

JavaScript

angular.module('app', [])
  // configFactory
  .factory('configFactory', function($q, $interval) {
    var config = null;
    var callbacks = [];

    // mock changes in configuration
    $interval(function() {
      function getTicks() {
        return (new Date()).getTime();
      }

      config = getTicks();
      angular.forEach(callbacks, function(callback) {
        callback(config);
      });
    }, 1000);

    // factory impl      
    return {
      // get resolved config promise
      getConfig: function() {
        return $q.when(config);
      },
      // register callbacks
      register: function(callback) {
        var index = callbacks.indexOf(callback);
        if (index === -1) {
            callbacks.push(callback);
        }
      },
      // unregister callbacks
      unregister: function(callback) {
        var index = callbacks.indexOf(callback);
        if (index === -1) {
            callbacks.splice(index, 1);
        }
      }
    };
  })

  // directive      
  .directive('directive', function(configFactory){
    return {
      restrict: 'E',
      replace: true,
      template: '<div>{{ config }}</div>',
      link: function(scope) {
        // get initial value
        configFactory.getConfig().then(function(config) {
          scope.config = config;
        });

        // callback fn
        var callback = function(config) {
          scope.config = config;
          console.log(config);
        };

        // register callback            
        configFactory.register(callback);

        // when scope is destroyed, unregister callback
        scope.$on('$destroy', function() {
          configFactory.unregister(callback);
        });
      }
    };
  });

Template

<body> 
  <directive></directive>
</body>

See related plunker here https://plnkr.co/edit/ZVyLPm

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you I am marking your answer as the correct and I appreciate all your help. As I look into my issue more it appears that my biggest problem is not updating the value but once the google analytics is called. When the config file changes and the GA id is updated I need to re-initialize the google analytics code

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.