How to decorate current state resolve function in UI-Router? Current function isn't invoked

后端 未结 2 1560
借酒劲吻你
借酒劲吻你 2020-12-10 08:32

I\'m trying to DRY in $stateProvider and prevent adding the same auth function in each resolve. I\'ve created decorator that in each state change w

相关标签:
2条回答
  • 2020-12-10 09:24

    If I understand your requirement correctly, we can use native UI-Router built-in decorator:

    decorator(name, func)

    Allows you to extend (carefully) or override (at your own peril) the stateBuilder object used internally by $stateProvider. This can be used to add custom functionality to ui-router, for example inferring templateUrl based on the state name... (read more in the doc)

    There is a working plunker

    So, we can have this var auth

    var auth = ['AuthService', '$stateParams',
      function(AuthService, $stateParams) {
        //how to invoke this function on needed states?
        if (AuthService.isAuthenticated()) {
          return AuthService.me();
        } else {
          return false;
        }
      }
    ];
    

    And here we just use decorator with some "IF" logic

    .config(['$stateProvider', 
      function($stateProvider) {
    
        $stateProvider.decorator('views', function(state, parent) {
          var result = {},
            views = parent(state);
    
          // some naive example when to not inject resolve
          if (state.name === "home") { 
            return views;
          }
          // child already has that in parent
          if (state.name.indexOf(".") > 0) { 
            return views;
          }
    
          angular.forEach(views, function(config, name) {
    
            // here inject the resolve (if not existing)
            config.resolve = config.resolve || {};
            // and extend it with the auth stuff above
            config.resolve.auth = auth;
    
            result[name] = config;
          });
    
          return result;
        });
    
      }
    ])
    

    And later few our states, which will be extended by the above stuff

    $stateProvider
        .state('home', {
          url: "/home",
          templateUrl: 'tpl.html',
        })
        .state('parent', {
          url: "/parent",
          templateUrl: 'tpl.html',
          controller: 'SharedCtrl',
        })
        .state('parent.child', {
          url: "/child",
          templateUrl: 'tpl.html',
          controller: 'SharedCtrl',
        });
    

    Check it in action here

    0 讨论(0)
  • 2020-12-10 09:29

    I realized that $delegate.current object contains only raw stateProvider config data. To wrap resolve function I add my function to $delegate.$current on each state change.

    $provide.decorator('$state', function($delegate, $rootScope) {
      $rootScope.$on('$stateChangeStart', function(event, state, params) {
        if ($delegate.current === "err404" || $delegate.current === "login" || $delegate.current === "register") {
          return;
        }
        console.log("decorator", $delegate);
        $delegate.$current.resolve["auth"] = ['AuthService', '$stateParams', function(AuthService, $stateParams) {
          if (AuthService.isAuthenticated()) {
            console.log('AuthService.me()');
            return AuthService.me();
          } else {
            return false;
          }
        }]
      });
      return $delegate;
    });
    

    Update

    I found related discussion on github, you can add universal resolve function into toState param:

    app.run(['$rootScope', '$state',
      function($rootScope, $state) {
    
        $rootScope.$on('$stateChangeStart', function(event, toState) {
    
          if (toState.name === "login" || toState.name === "register") {
            return;
          }
    
          toState["resolve"]["auth"] = ['AuthService', '$stateParams', function(AuthService, $stateParams) {
            if (AuthService.isAuthenticated()) {
              return AuthService.me();
            } else {
              return false;
            }
          }];
        });
      }
    ]);
    
    0 讨论(0)
提交回复
热议问题