What is the best way to do error handling globally in an angular.js app?

angularjs

Solution

The way I have implemented this is with a `messageService` that exposes the following interface:

{
    messages:      /* an array of all messages */,
    addMessage:    /* function(severity, text) */,
    removeMessage: /* function(messageObject) */,
    // other stuff, irrelevant to current topic
}

Each message object has a text, a "severity" (ERROR, WARNING etc) and a remove method. I have also added an option for messages to timeout and be removed automatically.

Any controller that needs to add messages, uses the `messageService`. A messages controller exposes the `messages` property of the service to its scope and the template `ng-repeat`s over them (I want to display messages at the top of the page). Using bootstrap styles:

<div id="messageContainer" ng-controller="messages">
    <div alert
         ng-repeat="msg in messages"
         type="msg.severity"
         close="closeMsg($index)"
    >
        {{msg.text}}
    </div>
</div>

And the controller:

app.controller("messages", ["$scope", "messageService"],
function($scope, messageService) {
    $scope.messages = messageService.messages,
    $scope.closeMsg = function(index) {
        $scope.messages[index].remove();
    };
});

Now, if a service needs to add a message, it can interact with the `messageService`. I'd rather not have services interact with the UI though; I think it is better for a service to return a list of messages and for the controller to deal with them as it wishes.

Problem

I have an app which makes http calls using various services I created. When the server request fails or when the api returns an error attribute I would like to display these errors on the top of my page. I can see in the angular documentation that error can best be displayed this way, which makes sense: ``` <div ng-controller="AlertDemoCtrl"> <alert ng-repeat="alert in alerts" type="alert.type" close="closeAlert($index)">{{alert.msg}}</alert> </div> ``` And in the AlertDemoCtrl: ``` $scope.addAlert = function() { $scope.alerts.push({msg: "Another alert!"}); }; $scope.closeAlert = function(index) { $scope.alerts.splice(index, 1); }; ``` The thing is that I'm not sure how to push the errors into the alerts within the AlertDemoCtrl since the http request is happening within the services where I don't have access to the AlertDemoCtrl. Do I need to broadcast events in order to add them into the AlertDemoCtrl or is there a way to inject a controller into a service? Or do I need to add the addAlert function into $rootScope? Appreciate any advice, thank you!

Original source