Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS error handling when resolving stuff inside the router?

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 the questions in the comments. Any clues, hints are very welcome!!

like image 298
Michael Heuberger Avatar asked Mar 19 '23 16:03

Michael Heuberger


1 Answers

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.

like image 177
Hugo Wood Avatar answered Apr 08 '23 09:04

Hugo Wood