btford / ngmin

**deprecated** AngularJS Pre-minifier –> use ng-annotate –>
https://github.com/olov/ng-annotate
860 stars 42 forks source link

Will this work with $routeProvider resolve functions? #23

Closed Siyfion closed 11 years ago

Siyfion commented 11 years ago

So I've got some route handling code like:

var authFilter = function ($location, userSession) {
    if (!userSession.isAuthenticated()) {
      $location.path('/user/login');
      return false;
    }
    return true;
  };

  angular.module('myApp')
    .config(function ($routeProvider) {
      $routeProvider
        .when('/', {
          templateUrl: 'views/home.html'
        })
        .when('/admin', {
          templateUrl: 'views/admin.html',
          resolve: { authFilter: authFilter }
        })
        .when('/user/login', {
          templateUrl: 'views/user_login.html',
          controller: 'UserLoginCtrl'
        })
        .otherwise({
          redirectTo: '/'
        });
    });

Only problem is that the resolve function breaks everything when minified; is there a way around this?

btford commented 11 years ago

Move authFilter into a service and inject it.

angular.module('myApp')
  .factory('authFilter', function ($location, userSession) {
    return function () {
      if (!userSession.isAuthenticated()) {
        $location.path('/user/login');
        return false;
      }
      return true;
    };
  });

  angular.module('myApp')
    .config(function ($routeProvider, authFilter) {
      $routeProvider
        .when('/', {
          templateUrl: 'views/home.html'
        })
        .when('/admin', {
          templateUrl: 'views/admin.html',
          resolve: { authFilter: authFilter }
        })
        .when('/user/login', {
          templateUrl: 'views/user_login.html',
          controller: 'UserLoginCtrl'
        })
        .otherwise({
          redirectTo: '/'
        });
    });

This not only solves the problem, but in general it's best to avoid global variables.

Siyfion commented 11 years ago

Apologies, that was me just being stupid. I should have thought to refactor the code into a service; makes perfect sense. :flushed:

Siyfion commented 11 years ago

Alas, upon trying this out, it doesn't seem to work. I get the following error: Unknown provider: authFilter from myApp.

Then someone reminded me that the only thing that can be injected into a config block is a provider or a constant. So I changed the authFilter to:

angular.module('myApp')
    .provider('authFilter', function ($location, userSession) {

      this.$get = function () {
        return function () {
          if (!userSession.isAuthenticated()) {
            $location.path('/user/login');
            return false;
          }
          return true;
        };
      };
    });

but then I just get Unknown provider: $location from myApp.

Can't seem to win with this one. :\

btford commented 11 years ago

Can you check if provider('authFilter')... is being annotated in your output file?

Siyfion commented 11 years ago

@btford Yeah, it is being annotated correctly; it's not an ngMin issue any more. Just can't figure out how else to do it. :/

btford commented 11 years ago

Weird. If you have more info on this, please let me know and I'll re-open this issue. As of now, it seems like the problem is outside of ngmin, so I'm going to close this.

Youdaman commented 11 years ago

I came across this issue when I had the exact same problem, and after much searching and trying different things, found the solution:

Instead of

    .config(function ($routeProvider, authFilter) {

It should be just

    .config(function ($routeProvider) {

and insted of

          resolve: { authFilter: authFilter }

it should be

          resolve: { authFilter: 'authFilter' }

I worked it out after reading http://stackoverflow.com/a/16322169/67675 and the docs about $routeProvider, specifically with regards to the resolve parameter: http://docs.angularjs.org/api/ng.$routeProvider

Hope this helps @Siyfion :)

BinaryMuse commented 11 years ago

@Youdaman is right on the money.

As an additional note, to inject $location and other non-providers for use in your authFilter, inject them into the $get method of your provider, instead of the provider itself:

angular.module('myApp')
    .provider('authFilter', function () {

      this.$get = function ($location, userSession) {
        return function () {
          if (!userSession.isAuthenticated()) {
            $location.path('/user/login');
            return false;
          }
          return true;
        };
      };
    });

ngmin will also annotate these.

Of course, now that Youdaman has shown how to use the service with $routeProvider, you can turn authFilter back into a regular ol' factory, and inject into it as normal.

Youdaman commented 11 years ago

Thanks @BinaryMuse -- your SO post was the clue :)

I haven't seen ".provider" before so thanks for that also, as well as the hint about injection into the $get instead.

Siyfion commented 11 years ago

Awesome, cheers guys! :+1:

pluma commented 10 years ago

In case anybody else finds this issue via Google: this issue was duplicated as #35 and should be addressed with PR #61.

martinpagesaal commented 10 years ago

Hey I had the same problem and I solved like this... a mix of the stuff before... (this is the only way I could make it work)

'use strict';

angular.module('srcApp', [...]) .provider('userChecker', function() { this.$get = function($location, $route, UserService) { // UserService is a service module in the code.

  var onUserSuccess = function(profile) {... to correct path ...};
  var onUserError = function(error) { ... To login ... }

  return UserService.getUser().then(onUserSuccess, onUserError);
};

}) .config(['$routeProvider', function($routeProvider) { $routeProvider .when('/dashboard', { access:{isParentRoute:false, isChildRoute:false}, resolve:{ userChecker : 'userChecker' } }) .when('/login', { templateUrl: 'views/login/student.html', controller: 'LoginCtrl', access:{isParentRoute:true, isChildRoute:true}, resolve:{ userChecker : 'userChecker' } }) .when ... .when ... .when ... .otherwise({ redirectTo: '/login', access:{isParentRoute:false, isChildRoute:true} }); }])