-2

I have a controller which has a number of $rootScope.$broadcast which update the contents of a directive.

The first $rootScope.$broadcast is clearing all the contents/data whilst the other populates it.

app.controller('MyController', function($scope, header) {

    $rootScope.$broadcast('clear');
    $rootScope.$broadcast('title', header.title);
    $rootScope.$broadcast('total', header.total);

});

Note: header is resolved from my $stateProvider e.g:

.state('index', {
        url: '/index',
        templateUrl: 'home.html',
        controller: 'MyController',
        resolve: {
            header:  function() {
                return {
                    title : 'Welcome to Home',
                    total : 6
                };
            }
        }
    })

directive:

app.directive('myDirective', function() {
    return {
        restrict: 'A',
        replace: true,
        scope: {},
        link: function(scope, element, attrs) {
            scope.$on("clear", function(event, val) {
                scope.Title = '';
                scope.Total = 0;
            });               
            scope.$on("title", function(event, title) {
                scope.Title = title;
            });
            scope.$on("total", function(event, total) {
                scope.Total = total;
            });
        },
        template:
            '<section>' +
                '<p>{{Title}} - {{Total}}</p>' +                        
            '</section>'
    }
});

The problem I am having is that on page load, the $broadcast of title and total appear to be being called before clear has completed.


UPDATE:

Plunker: http://plnkr.co/edit/o7wEFyIGh0284ZAc9VnS?p=preview

Whenever on the home.html, the directive will hide - correct. Whenever on the cart.html, the directive will show - correct.

To see issue, click on Cart... Click the button to increment counter.. Then go back to home, then back to Cart... the counter will not reset to 0

Oam Psy
  • 8,555
  • 32
  • 93
  • 157
  • http://stackoverflow.com/questions/18130369/emit-broadcast-synchronous-or-asynchronous – Daniel Lizik Aug 27 '15 at 14:22
  • So when you put console.log statements in the three $on, "clear" logs last? – camden_kid Aug 27 '15 at 14:27
  • @camden_kid - please see the attached updated plunker and comments – Oam Psy Aug 27 '15 at 15:44
  • 1
    If you look at the console with this Plunker - http://plnkr.co/edit/mjEt5j7H2cV3i3rpM6BQ?p=preview, you can see that the events are called synchronously. – camden_kid Aug 27 '15 at 16:24
  • 1
    Also, why do you need to have three broadcasts? Have just one like this : $rootScope.$broadcast('new', {title: headerCart.title, showDirective: headerCart.showDirective}); – camden_kid Aug 27 '15 at 16:27
  • @camden_kid - good idea ^ i'll refactor once i solve the why would {{Total}} not get set to 0 when the cart state is loaded through $rootScope.$broadcast('clear'); issue – Oam Psy Aug 27 '15 at 16:28
  • See my updated Plunker. – camden_kid Aug 27 '15 at 16:38
  • @camden_kid - thanks, so a couple of points. The myService.inititate(); should not be commented out as they need to be ran on load. Secondly, if you update the counter.. Go to home, then back to cart, update the counter, it doesnt start from 0, but where you last left the counter. – Oam Psy Aug 27 '15 at 17:01
  • I think the problem is that the scope.Total within clear isn't updating scope.Total globally... – Oam Psy Aug 27 '15 at 17:48

2 Answers2

1

You should use service for synchronization like this:

app.controller('MyController', function($scope, header, myDirectiveManager) {
  myDirectiveManager.getPromise().then(function(directive){
    directive.clear();
    directive.setTitle(header.title);
    directive.setTotal(header.total);
 });

});

service

app.service('myDirectiveManager',function($q){
   var deferred = $q.defer();
   this.getDeffer = function(){
     return deferred;
   };
   this.getPromise = function(){
      return deferred.promise;
   }
});

directive

app.directive('myDirective', function() {
return {
    restrict: 'A',
    replace: true,
    scope: {},
    controller: function($scope, myDirectiveManager) {
        var fasade = {
           clear: function(event, val) {
            scope.Title = '';
            scope.Total = 0;
           },
           setTitle: function(event, title) {
            scope.Title = title;
           },
           setTotal: function(event, total) {
            scope.Total = total;
           }

        };
        myDirectiveManager.getDeffer().resolve(fasade);
    },
    template:
        '<section>' +
            '<p>{{Title}} - {{Total}}</p>' +                        
        '</section>'
    }
  });
0

As mentioned in my comment above, the problem was that scope.Total within 'clear' was/is not accessible in other .on casts. So, a global variable has been declared and updated within each broadcast:

app.directive('myDirective', function() {
  return {
    restrict: 'A',
    replace: true,
    scope: {},
    link: function(scope, element, attrs) {

      var localTotal = null;

      scope.$on("clear", function(event) {
        scope.Title = '';
        scope.Total = 0;
        localTotal = scope.Total;
      });
      scope.$on("showDirective", function(event, show) {
        scope.showDirective = show;
      });
      scope.$on("total", function(event, total) {
        if (localTotal !== 0) {
          console.log("in IF");
          scope.Total = total;
        }
        else {
          scope.Total = localTotal;
        }
      });
      scope.$on("title", function(event, title) {
        scope.Title = title;
      });
    },
    template: '<section>' +
      '<p ng-if="showDirective">{{Title}} - {{Total}}</p>' +
      '</section>'
  }
});

See Plunker: http://plnkr.co/edit/2Xx99RzvQtaD9ntiod0d?p=preview

Oam Psy
  • 8,555
  • 32
  • 93
  • 157