jrquick jrquick - 5 months ago 29
AngularJS Question

Angular controller $on only picks up when initialized within controller calling $broadcast

I am trying to create a controller that picks up error messages and handles them:

ngLogin.controller('ErrorCtrl', ['$scope', '$rootScope', function($scope, $rootScope) {
$scope.$on('ngError', function(event, args) {
$scope.displayErrors(args);
});

$scope.displayErrors = function(errors) {
alert(errors);
}
}]);


Other controllers are meant to broadcast errors like so:

ngLogin.controller('LoginCtrl', ['$scope', 'LoginService', '$controller', '$rootScope', function($scope, LoginService, $controller, $rootScope) {
$scope.login = function(callback) {
LoginService.login($scope.user.username, $scope.user.password, function(token) {
//SUCCESS
}, function(errors) {
$rootScope.$broadcast('ngError', errors);
});
};
}]);


My problem is this does not work without the following code added to each of the broadcasting controllers:

$scope.ErrorCtrl = $scope.$new();
$controller('ErrorCtrl', {
$scope: $scope.ErrorCtrl
});


index.html

<script src="app.js"></script>
<script src="../src/LoginService.js"></script>
<script src="../src/LoginCtrl.js"></script>
<script src="../src/ErrorCtrl.js"></script>


Is there not another way? I would prefer not to have to use the last piece of code in EVERY controller that needs this error handling. When I remove it the ErrorCtrl never receives the event.

Answer

I'd say that create a service will be responsible for just showing an error messages & have a event listener code inside application run phase.

app.run(function($rootScope, errorService){
   //listner here
   $rootScope.$on('ngError', function(event, args) {
    $scope.displayErrors(args);
  });
});
app.service('errorService', function(){
   var errorService = this;
   errorService.displayErrors = function(errors){
       alert(errors)
   };
})

Or more convenient way would be just call service displayErrors method to display error messages whenever you want, by which you can eliminate events based approach from your application.

ngLogin.controller('LoginCtrl', ['$scope', 'LoginService', '$controller', '$rootScope', 'errorService', function($scope, LoginService, $controller, $rootScope, errorService) {
    $scope.login = function(callback) {
        LoginService.login($scope.user.username, $scope.user.password, function(token) {
            //SUCCESS
        }, function(errors) {
            errorService.displayErrors(errors); //call display error method here.
        });
    };
}]);