Gedalya
Gedalya

Reputation: 909

Angular $scope.$broadcast Event Only Executed One Time

I have two pieces of code in two separate Controllers (in two separate JS files); one triggers an Angular $scope.$broadcast event, and the other an $scope.$on listener.

First Controller (file) snippet:

var Controller1 = function($scope) {
    $scope.triggerMyEvent = function(){
        $scope.$broadcast('triggeredEvent');
    }
    $scope.go = function ( path ) {
        $location.path( path );
    };
}

Second Controller (file) snippet:

var Controller2 = function($scope) {
    $scope.$on('triggeredEvent',function(event){
        console.log('found triggered event');
    });
}

The application is wired together as follows:

var app = angular.module("myApp", ["ngRoute"]);
app.config(function($routeProvider) {
   $routeProvider
    .when("/page2", {
        controller : Controller2
        template : "/page2.html"
     })
    .otherwise({
        template : "<p>Error</p>"
    });
});

The first Controller is referenced by a ng-controller directive in the index.html file; and the other file, page2.html listed above is referenced and loaded from actions on the index:

index.html:

<body ng-controller="Controller1">
    <button ng-click="go('/page2.html')">Page 2</button>
</body>

The first time I load up this code the $scope.$broadcast event is triggered and the $scope.$on listener catches it just fine; if I reload it though the $scope.$on listener doesn't catch it. To be clear, on an initial load the event is triggered and caught just fine; so when restart my server and access the page. However if I refresh the page (F5), I believe the event is being fired but not caught. I'm new to working with this so I am presuming a some lack of knowledge however I have read up on $scope/$rootScope and things like $broadcast/$emit/$on. Any help is appreciated. I see a number of articles on related issues; not seeing anything imminently relevant; although I did note this article:

Angular $broadcast only updating after page refresh

AngularJS event-based communication through isolate scope

The most promising references I believe related to Isolate scope but I have not been able to get anything to work yet.

Upvotes: 1

Views: 1925

Answers (1)

Pop-A-Stash
Pop-A-Stash

Reputation: 6652

$broadcast and $on work through the scope hierarchy. $broadcast sends a message down the scope hierarchy toward it's descendants. Any $on listeners must be a descendant of the scope that the message was broadcast from. If you broadcast from the $rootScope, then every scope will be a descendant and every scope will be able to listen to the message. So, one way to ensure that your message is reachable by all scopes is to broadcast it like so:

// just to demostrate. don't put this in a controller
$scope.triggerMyEvent = function(){
    $rootScope.$broadcast('triggeredEvent');  //don't do this in a controller
}

Ideally, you don't want litter root scope with messages. (Actually you should really never do this. It's even worse if you use $rootScope.$on in a controller as it adds and retains a new listener everytime the controller is initialized). To get to the root of your problem(pun intended) you need to pay attention to this hierarchy, as this will affect your listeners.

One example of this hierarchy:

<div ng-controller="ParentCtrl">
  <div ng-controller="ChildCtrl">
  </div>
</div>

<div ng-controller="SiblingCtrl">
</div>

function ParentCtrl($scope) {
  $scope.$broadcast('parentMsg');
}

function ChildCtrl($scope) {
  $scope.$on('parentMsg', function() {
    // will receive message
  });
}

function SiblingCtrl($scope) {
  $scope.$on('parentMsg', function() {
    // will not receive message
  });
}

Upvotes: 1

Related Questions