如何从父状态的嵌套状态访问参数?
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"];
})
我只看到两种方式:
- 添加服务并将其注入两个控制器
- 从子控制器访问父作用域并传递参数
但两者都让我在父范围内添加观察者。
也许我可以更轻松地完成它?
我不确定这是否真的能解决您的问题,但您可以这样做
$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;
});
同理,如果只需要放在视图中,那么在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;
}]);
通过这种方式,子级和父级都可以使用参数。
我有一个例子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"];
})
我只看到两种方式:
- 添加服务并将其注入两个控制器
- 从子控制器访问父作用域并传递参数
但两者都让我在父范围内添加观察者。 也许我可以更轻松地完成它?
我不确定这是否真的能解决您的问题,但您可以这样做
$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;
});
同理,如果只需要放在视图中,那么在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;
}]);
通过这种方式,子级和父级都可以使用参数。