4

I've been doing lots of research on how to deal with errors best. Let's assume I have this AngularjS code:

$routeProvider

    .when('/videomail/:key', {
        templateUrl : 'view.html',
        controller  : 'ViewCtrl',
        title       : 'View',
        hideHeader  : true,
        hideFooter  : true,
        resolve: {
            videomail: function($rootScope, $route, Videomail) {
                return Videomail.get({key: $route.current.params.key}).$promise.then(function(videomail) {
                    return videomail
                }, function(err) {
                    // How can I present the error here?
                    // Should I return it like 'return err' and let the controller deal with it?
                    // Or can I forward this to another controller?
                    // PS: It can be a 404 or a 401 error 
                })
            }
        }
    })

Check out my questions in the code comments. What can I try next?

1
  • you want to do it in general for all aplication error handling or only for this route ? Commented Aug 21, 2014 at 8:36

2 Answers 2

4

Since you don't want the route to change, and you don't want to handle the error in the controller, you can do this:

  • Resolve the promise with something that is unambiguously an error. You have to resolve the promise because if you don't, the route will not be loaded at all, and you can't change that in $routeChangeError.

    videomail: function($rootScope, $route, Videomail) {
        return Videomail.get({key: $route.current.params.key}).$promise.then(function(videomail) {
            return videomail
        }, function(err) {
            return { resolveError: err }
        })
    }
    
  • Somewhere in the app (maybe in run), intercept $routeChangeSuccess and check if an error occured.

    $rootScope.$on('$routeChangeSuccess', 
        function (event, current, previous) {
            if (current.locals.videomail && current.locals.videomail.resolveError) {
                current.locals.$template = $templateCache.get('error.html')
                $rootScope.error = current.locals.videomail.resolveError
            }
        }
    )
    

Now you just have to write a template named error.html that will display something depending on the error object present in the scope.

DEMO

It works but I think it is kind of a hack. I don't believe Angular was meant to be used that way.

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

Comments

3

You can use the $location service to redirect to another route.

return Videomail.get({key: $route.current.params.key}).$promise.then(function(videomail) {
    return videomail
}, function(err) {
    $location.path('/error')
})

7 Comments

Thanks, good idea. But how can I pass on the err object to the new error page? Or should I be using the $routeChangeError event instead?
You pass the error members in the URL with $location.search. $routeChangeError is another possibility if you want to handle errors application-wide.
I just played and $location.path() is not what I want. Because it's a redirect, the URL changes. But I want the URL to stay.
So I assume $routeChangeError is the solution for me but I haven't figured out how I can set a template inside the $routeChangeError event handler?
As far as I know, you cannot do that. If a promise is rejected, the controller and the view for the route are not loaded at all. The only thing you can do is redirect.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.