角度 ui-router 解析父状态 [英] angular ui-router resolve for parent state

查看:18
本文介绍了角度 ui-router 解析父状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

In my parent state I have a resolve. Currently, I do not inject the resolve key in any child state.

I assumed that my child state would not wait for this resolve/promise to be resolved. But when I set a timeout, I can see my child state does wait.

Is this correct behaviour?

.config(function ($stateProvider, $urlRouterProvider, STATES) {
    $stateProvider
        .state(STATES.ROOT, {
            abstract: true,
            template:'<div ui-view=""></div>',
            resolve: {                  
                UserService: 'UserService',
               userDetails: function(UserService){
                   return UserService.getUserProfile();
                }

            }
        })
        .state(STATES.BILLING, {
            url: '/bill/checkClientContext.html',
           templateUrl: 'bill/checkClientContext.html',
            controller: 'BillingController'
        })

UserService.js

'use strict';
angular.module('nabc.data')
    .service('UserService', ['AjaxService', '$timeout','$q', function(AjaxService, $timeout, $q) {
        var getUserProfile = function() {
            var promise = AjaxService.get('userProfile');

            var deferred = $q.defer();
            $timeout(function(response){
                deferred.resolve(response);
            }, 5000);
            return deferred.promise;


        };

        return {
            getUserProfile: getUserProfile
        };
    }]);

As you can see above the BillingController does not inject in userDetails. But when i set a timeout in the userService, i see that my billing state does wait.

解决方案

The answer could be found here (let me cite few lines and snippet):

Inherited Resolved Dependencies

New in version 0.2.0

Child states will inherit resolved dependencies from parent state(s), which they can overwrite. You can then inject resolved dependencies into the controllers and resolve functions of child states.

$stateProvider.state('parent', {
      resolve:{
         resA:  function(){
            return {'value': 'A'};
         }
      },
      controller: function($scope, resA){
          $scope.resA = resA.value;
      }
   })
   .state('parent.child', {
      resolve:{
         resB: function(resA){
            return {'value': resA.value + 'B'};
         }
      },
      controller: function($scope, resA, resB){
          $scope.resA2 = resA.value;
          $scope.resB = resB.value;
      }

So, as we can see in the doc, resolve on parent could be used on a child. And that is in fact reason, while we have to wait for this to be resolved... before we can continue.

But I would say, that this is expected. The more fancy feature would be:

if the child state has defined resolve - and parent does not - it would be great to see parent views rendered, and let only child's views to wait.

This is (as far as I know) planned in the near future as a feature...

EXTEND - await all to continue is the answer

To get the answer:

Must all the resolves - declared in current state and all its parent states - be awaited to continue with current? Even if current state controllers do not require any of these values?

Do observe the code: state.js

function resolveState(state, params, paramsAreFiltered, inherited, dst, options) {
  // Make a restricted $stateParams with only the parameters that apply to this state if
  // necessary. In addition to being available to the controller and onEnter/onExit callbacks,
  // we also need $stateParams to be available for any $injector calls we make during the
  // dependency resolution process.
  var $stateParams = (paramsAreFiltered) ? params : filterByKeys(state.params.$$keys(), params);
  var locals = { $stateParams: $stateParams };

  // Resolve 'global' dependencies for the state, i.e. those not specific to a view.
  // We're also including $stateParams in this; that way the parameters are restricted
  // to the set that should be visible to the state, and are independent of when we update
  // the global $state and $stateParams values.
  dst.resolve = $resolve.resolve(state.resolve, locals, dst.resolve, state);
  var promises = [dst.resolve.then(function (globals) {
    dst.globals = globals;
  })];
  if (inherited) promises.push(inherited);

  // Resolve template and dependencies for all views.
  forEach(state.views, function (view, name) {
    var injectables = (view.resolve && view.resolve !== state.resolve ? view.resolve : {});
    injectables.$template = [ function () {
      return $view.load(name, { view: view, locals: locals, params: $stateParams, notify: options.notify }) || '';
    }];

    promises.push($resolve.resolve(injectables, locals, dst.resolve, state).then(function (result) {
      // References to the controller (only instantiated at link time)
      if (isFunction(view.controllerProvider) || isArray(view.controllerProvider)) {
        var injectLocals = angular.extend({}, injectables, locals);
        result.$$controller = $injector.invoke(view.controllerProvider, null, injectLocals);
      } else {
        result.$$controller = view.controller;
      }
      // Provide access to the state itself for internal use
      result.$$state = state;
      result.$$controllerAs = view.controllerAs;
      dst[name] = result;
    }));
  });

  // Wait for all the promises and then return the activation object
  return $q.all(promises).then(function (values) {
    return dst;
  });
}

I decided to cite the complete method here, but the most important parts are: declaration of the var promises = [];. This array is later extended with all resolves required to continue promises.push($resolve.resolve(... and finally, untill all the stuff is not done, no result - return $q.all(promises)

这篇关于角度 ui-router 解析父状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆