在ui-router FAQ entry之后,我最近实现了一个通用的AngularJS服务,它将任何ui-router状态定义转换为包含ui-bootstrap模式的状态定义。
作为其中的一部分,需要将resolve
对象从状态定义下推到$modal.open()
选项。这个问题的主要问题是注入这些解析函数的$stateParams
是先前状态的$modal.open()
。经过多次努力解决这个问题之后,我发现只需将$timeout
调用包裹在$timeout
块中就会产生所需的行为。
一般情况下,我想了解为什么这样做的方式,无论是否是可接受的解决方案,以及是否涉及任何警告。在过去,我已经能够通过在$timeout
中包含一段代码来解决几个Angular时序问题,这让我感到紧张,因为我真的不确定它为什么会起作用。我猜测在当前的摘要周期结束后$timeout
迫使该块运行,但我对此并不太自信。
我创建了一个Plunker来演示这一点 - 如果删除$stateParams
并调用模态,则参数将无法解析。
注意:作为一个警告,我必须能够在模态结果中正确地解析$injector.invoke
- 我有许多现有的控制器和状态定义,我宁愿不必返回并重构。
后续行动:我已创建ui-router issue 1649以请求解决此问题 - 此外还有一个minimal Plunker仅使用{{1}}来演示无模式的问题所有
答案 0 :(得分:1)
这种情况正在发生,因为当secondparam正在解决时,您尚未转换到新状态。 $ timeout将您的代码放在队列的末尾,然后发生状态转换,然后执行具有预期状态的代码。您可以通过在解析配置中记录或警告当前状态来判断:
secondparam: ['$stateParams', function($stateParams) {
alert($state.$current.url); //here
return $stateParams.secondparam;
}]
不幸的是,onenter和onexit的文档并没有明确说明它们在生命周期中何时被调用:https://github.com/angular-ui/ui-router/wiki#onenter-and-onexit-callbacks。但是this post给出了一些指示:
这些回调使我们能够在新视图上触发操作 或者在我们前往另一个州之前。
我认为你最好使用控制器并在那里打开你的模态而不是$ timeout(我相信你的上下文将是window / global)。
$stateProvider.state('demo.modal', {
url: '/modal/:secondparam',
template: 'showing modal',
controller: function($scope, $modal, $state){
var modalInstance = $modal.open({
template: '<div class="alert alert-success" role="alert">Remove the $timeout and this will not resolve: {{secondparam}}</div>',
resolve: {
secondparam: ['$stateParams', function($stateParams) {
console.log($state.$current.url, $stateParams); //you are in the new state
return $stateParams.secondparam; //'secondparam' IS resolved, even without $timeout
}]
},
controller: function($scope, secondparam) {
$scope.secondparam = secondparam;
}
});
modalInstance.result.finally(function() {
$state.go('^');
});
}
});
请注意,我必须将<div ui-view></div>
添加到演示状态才能让控制器实例化(ui-router nested route controller isn't being called)。
$stateProvider.state('demo', {
url: '/demo/:firstparam',
template: '<button class="btn btn-primary" ui-sref=".modal({ secondparam: 2 })">Show Modal</button>' +
'<button class="btn btn-primary" ui-sref="demo.contacts">Show Contacts</button><div ui-view></div>'
});
答案 1 :(得分:1)
这可能是一种意外的行为,或onEnter
的“设计”行为。
解决方案是将$stateParams
注入onEnter
处理程序 - 它将指向onEnter
的第二个状态(根据documentation)的参数。
$stateProvider.state('demo.modal', {
url: '/modal/:secondparam',
onEnter: showModal,
// ...
});
function showModal($state, $stateParams) {
var secondparam = $stateParams.secondparam; // equals 2
...
// BUT, the state has not yet transitioned
var secondParamFromState = $state.params.secondparam; // is undefined
...
}
$timeout
允许状态转换,resolve
的{{1}}被注入当前参数,这将是第二个状态。
编辑:已更新plunker