如何从父状态的嵌套状态访问参数?

How to access parameter from nested state in parent state?

我有一个例子here。我如何访问父状态控制器中的 'itemId' 参数?不得重新加载父视图。

angular.module('app',['ui.router'])
.config(function($stateProvider){
   $stateProvider.state('step', {
            url: '/orders/:step',
            templateUrl: 'parent.html',
            controller: function ($scope, $stateParams) {
                $scope.itemId = $stateParams.itemId;
                $scope.step = $stateParams.step;
            }
        })

        .state('step.item', {
            url: '/:itemId',
            templateUrl: 'child.html',
            controller: function ($scope, $stateParams) {
                $scope.itemId = $stateParams.itemId;
                $scope.step = $stateParams.step;
            }

        });
}).controller('SimpleController', function($scope, $state){
  $scope.items = [1,2,3,4,5,6];
  $scope.steps = ["first", "second"];
})

我只看到两种方式:

  1. 添加服务并将其注入两个控制器
  2. 从子控制器访问父作用域并传递参数

    但两者都让我在父范围内添加观察者。 也许我可以更轻松地完成它?

我不确定这是否真的能解决您的问题,但您可以这样做

   $stateProvider.state('step', {
            url: '/orders/:step/:itemId',
            templateUrl: 'parent.html',

http://plnkr.co/edit/sYCino1V0NOw3qlEALNj?p=preview

这意味着父状态将在途中收集 itemID。

首先,你需要认识到 parent 状态的控制器在你进入它的 child 状态的子树时只运行一次,所以在它的 children 之间切换不会 re-run 控制器。

这就是说,如果您希望 itemId 参数始终保持最新,则需要 $watch(您试图避免)。

第一次,你可以在parent的状态下像这样收集itemId

$scope.itemId = $state.params.itemId;

如果您需要保留它up-to-date,那么您需要注意变化,例如:

$scope.$watch(function(){
  return $state.params;
}, function(p){
  $scope.itemId = p.itemId;
});

plunker

同理,如果只需要放在视图中,那么在scope上设置$state

$scope.$state = $state;

并且在视图中:

<div>parent /orders/{{step}}/{{$state.params.itemId}}</div>

编辑:

我想另一种方法是在 parent 上调用 scope-exposed 函数来更新值。我不喜欢这种方法,因为它依赖于范围继承(这并不总是与状态继承相同)并且大型应用程序中的范围继承很难跟踪。但它消除了对 $watch:

的需要

在 parent 控制器中:

$scope.updateItemId = function(itemId){
   $scope.itemId = itemId;
};

并在 child 控制器中:

if ($scope.updateItemId) $scope.updateItemId($stateParams.itemId)

我看得出来,您已经找到了答案,但我想向您展示不同的方法。我什至会把它命名为 "the UI-Router built in approach".

已在 UI-Router example application, where if we go to child state with some ID = 42 like here 中显示,我们还可以更改除主视图 (本例中的 hint 视图) 之外的其他视图。

有一个working example with your scenario,表示一切正常。

我们使用的是 Multiple Named Views

parent状态,现在定义根视图,注入到未命名的ui-view=""里面的root/index.html.

一个新的parent.html

<div ui-view="title"></div>
<div ui-view=""></div>

正如我们所见,它还包含另一个视图目标(而不是未命名的)——例如ui-view="title" 我们立即用另一个模板填充...处于 parent 状态:

$stateProvider.state('step', {
  url: '/orders/:step',
  views : {
    '': {
      templateUrl: 'parent.html',
    },
    'title@step': {
      templateUrl:'parent_title_view.html',
    }
  }
})

和child?它可以继续处理主区域...但也可以更改标题区域。两种观点都是独立的,属于child。

.state('step.item', {
  url: '/:itemId',
  views : {
    '': {
      templateUrl: 'child.html',
    },
    'title': {
      templateUrl:'child_title_view.html',
    }
  }

所以,没有观察者,什么都没有...默认情况下 UI-Router 没有附带。我们只是用 child 实现调整了许多地方(视图)。我们仍然可以在 parent..

中提供一些默认值的内容

检查 example here。希望以不同的方式看待它会有所帮助...

在父状态的解析函数中包含 $state

.state('parent', {
                url: '/parent',
                controller: 'parentController',
                resolve: {
                params: ['$state', function ($state) {
                            return  $state.params;
                        }]
                }
            })

然后在父控制器中注入resloved vars

app.controller('parentController', ['$scope', 'params',
function ($scope, params) {

  $scope.params = params; 

}]);

通过这种方式,子级和父级都可以使用参数。