31

I would like to resolve the promise that loads the current user for all the pages of my application. Currently I repeat the resolve in every $routeProvider.when() of my routes.

  $routeProvider.when('/users/edit/:userId', {
  templateUrl: 'app/app/assets/partials/user-edit.html', 
  controller: 'UserEditController',
  resolve:{  
    'currentUser':function( UserService){            
        return UserService.getCurrentUser();
      }
  }
  });  

  $routeProvider.when('/staff_profil/edit', {
  templateUrl: 'app/app/assets/partials/profil-edit.html', 
  controller: 'ProfilEditController',
  resolve:{  
    'currentUser':function( UserService){            
        return UserService.getCurrentUser();
      }
  }
 });

My goal is to resolve my current user for all the routes without repetition.

7 Answers 7

28

For completeness, here is the whole solution, using angular instead of underscore, with a chainable 'when'. Nothing new in this code, just combined a bunch of the answers above.

var originalWhen = $routeProvider.when;

    $routeProvider.when = function(path, route) {
        route.resolve || (route.resolve = {});
        angular.extend(route.resolve, {
            CurrentUser : function(User) {
                return User.current();
            }
        });

        return originalWhen.call($routeProvider, path, route);
    };
Sign up to request clarification or add additional context in comments.

1 Comment

This should be the right answer. For me the accepted answer throws error when I don't use .call
24

You could always wrap the existing when method on the $routeProvider with your own implementation.

var myModule = angular.module('myModule', ['ngRoute'])
   .config(['$routeProvider', function($routeProvider){

      var originalWhen = $routeProvider.when;

      $routeProvider.when = function(path, route){

         route.resolve = {
            'currentUser':function( UserService){            
              return UserService.getCurrentUser();
            }
         };

         return originalWhen(path, route);
      };   

   }]);

You probably want to add some error checking in there, and use something like underscores defaults method instead of just overwriting the existing resolve property, but at least this way you can guarantee all your routes will have what you want.

It's also easy enough to wrap this up into a helper method.

3 Comments

This looks great, but I get Error: [$injector:modulerr] Failed to instantiate module ... due to: $routeProvider.when(...) is undefined, even if all the override method does is return originalWhen(path, route); Instead, I appended a new method, $routeProvider.accessWhen, which can return $routeProvider.when(path, route);, and call .accessWhen instead of .when in my routes setup.
wouln't the 'currentUser' resolve be overwritten if you add the resolve-property in the actual route? Maybe route.resolve = route.resolve || { }; route.resolve.currentUser = ... would be better?
Can you do something similar wiith ui-router ?
4

The @Josh answer is correct, except you have to invoke originalWhen function differently:

originalWhen.call($routeProvider, path, route);

Comments

3

Both @N13 and I could not make @Josh's solution work. But this did work for me:

    module.config(['$routeProvider', function($routeProvider){
        $routeProvider.accessWhen = function(path, route){
            route.resolve || (route.resolve = {});
            route.resolve.language = "something"
            return $routeProvider.when(path, route);
        };
    }]);

use with:

$routeProvider
        .accessWhen('/login', {
           ...
        });

1 Comment

This seems like the simplest solution to me
2

I found that this case much better:

angular.extend({}, $routeProvider, {
  when: function(path, route) {
    route.resolve || (route.resolve = {});
    route.resolve = angular.merge({}, route.resolve, {
      chef: 'OrganizationCheckerProvider'
    });
    return $routeProvider.when(path, route);
  }
});

3 Comments

When the question is in javascript it should be answered in javascript.<br> This also use underscore... which he/she might not use
Endless, ok, changed to JS. lodash/underscore is preferred by me here, because it have excellent deep merge. He/she can try alternatives for lodash/underscore if not use.
AngularJS has angular.merge(destination, source) which looks similar to the lodash implementation _.merge().
0

For the people stuck with old code bases.

const _when = $routeProvider.when;
$routeProvider.when = (path, route) => _when.call($routeProvider, path, {
  ...route,
  resolve: {
    ...route.resolve,
    'currentUser': [ 'UserService', UserService => UserService.getCurrentUser() ]
  }
});

Comments

0

Combining all answers together

var myModule = angular.module('myModule', ['ngRoute'])
        .config(['$routeProvider', function ($routeProvider) {
            var originalWhen = $routeProvider.when;

            $routeProvider.when = function (path, route) {
                route.resolve || (route.resolve = {});
                angular.extend(route.resolve, {
                    CurrentUser: ['User', function (User) {
                        return User.current();
                    }]
                });
                return originalWhen.call($routeProvider, path, route);
            };
        }]);

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.