如何在ui-router中持久化浏览器上的可选状态参数
How to persist optional state parameter on browser back in ui-router?
我有一个父状态里面有两个子状态我将显示一个基于URL
的状态
在这两个states
中,一个有param1
和param2
这样的参数,我在状态定义中使用了ui-router的params
选项。
$stateProvider.state('tabs.account', {
url: '/account',
views: {
'content@tabs': {
templateUrl: 'account.html',
controller: function($scope, $stateParams) {
//This params are internally used to make ajax and show some data.
$scope.param1 = $stateParams.param1;
$scope.param2 = $stateParams.param2;
},
}
},
params: {
param1: { value: null }, //this are optional param
param2: { value: null } //because they are not used in url
}
});
如果你看看我的路由,params选项并没有真正在URL
中引入,这就是为什么我认为它是可选的。
看看plunkr,我已经展示了两个选项卡Account & ,
- 点击调查选项卡,然后在
textarea
中添加一些显示的数据。 点击转到帐户,将这些
textarea
值传递给通过在锚 上执行现在你将看到
param1
&从$stateParams
中分配给范围的html的- 点击浏览器返回,你会注意到
param
的值没有得到null
。
ui-sref="tabs.account({param1: thing1, param2: thing2})"
来更改另一个帐户选项卡param2
值现在再次点击调查标签,您将进入调查页面。问题Plunkr
我相信你得到了我想问的,为什么可选参数值没有被存储?因为他们已经是国家的一部分。
我知道我可以用以下两种方法来解决这个问题。
- 通过创建一个服务来在两个视图之间共享数据。
- 通过在状态URL中添加参数。像
url: '/account/:param1/:param2',
(但我不喜欢这个)
我已经尝试过angular-ui-路由器 sticky states
,但这似乎不适合我。有什么更好的方法吗?
有什么方法可以让我的用例工作,任何想法都将不胜感激。
Github Issue Link Here
我会将params
定义移动到父状态,以便在您的两个子状态之间共享可选状态参数。
子状态将从父状态继承$stateParams
,因此不需要真正的"变通方法"。
只要像往常一样在子控制器中注入$stateParams
,您就可以完全访问正在传递的参数。如果不想在特定的子状态中使用参数,只需避免注入它们。
这适用于;
- 后退按钮
- 前进按钮
- ui-sref (不带参数(保持原样))
- ui-sref (带参数(将覆盖))
$stateProvider
.state('parent', {
params: { p1: null, p2: null }
})
.state('parent.childOne', {
url: '/one',
controller: function ($stateParams) {
console.log($stateParams); // { p1: null, p2: null }
}
})
.state('parent.childTwo', {
url: '/two',
controller: function ($stateParams) {
console.log($stateParams); // { p1: null, p2: null }
}
})
如果您在parent
的状态树中旅行时想要清除参数,则必须手动执行。
这将是唯一的真正的警告,我可以看到通过使用这个解决方案。
我知道在你提出的情况下,手动清理可能不可取,但你并没有积极反对,因此我觉得这个建议是有价值的。
更新的plunker
一个解决方案是缓存状态参数,并在进入tabs.account
状态时有条件地加载它们。UI Router状态配置实际上允许你为这些类型的"进入状态时做点什么"的情况提供一个onEnter
回调。
下面是使用localStorage作为缓存的基本逻辑,这里有工作的Plunker:
- 当您进入
tabs.account
状态时,检查您的状态参数- 如果你有,缓存到本地存储
- 如果没有,从本地存储加载到
$stateParams
这里有一个示例代码片段供参考(取自Plunker):
$stateProvider.state('tabs.account', {
...
onEnter: ['$stateParams', '$window', function($stateParams, $window) {
if($stateParams.param1) {
$window.localStorage.setItem('tabs.account.param1', $stateParams.param1);
} else {
$stateParams.param1 = $window.localStorage.getItem('tabs.account.param1');
}
if($stateParams.param2) {
$window.localStorage.setItem('tabs.account.param2', $stateParams.param2);
} else {
$stateParams.param2 = $window.localStorage.getItem('tabs.account.param2');
}
}],
...
}
一个警告是你的参数将无限期地持续(例如跨刷新和会话)。为了解决这个问题,您可以在应用程序加载时清除缓存,如app.run
所示。
最后需要注意的是,在Plunker中,我直接访问了本地存储(通过Angular的$window
服务)。你可能想使用一些AngularJS模块——我已经在生产中使用了angular-local-storage。
我相信,如果不使用您提供的两种解决方案之一,您想要实现的目标是不可能实现的。
浏览器后退按钮只是保存URL历史记录。他不知道ui-router的内部状态,只会强迫URL改变。
强制修改URL会触发ui-router内部机器,但不幸的是,ui-router会看到URL的变化,就像有人手工修改URL一样。
Ui-router将触发一个新的路由变更到URL所指向的路由。这意味着他不知道你想"回去",只会在没有任何参数的情况下将状态更改为新状态。
单击后退按钮将根据URL触发状态更改为新的状态,而不是返回到以前的状态。
这就是为什么在URL中添加参数可以解决这个问题。因为URL是歧视性的,你最终会到达你想要的状态。
希望有帮助。
对我来说这听起来像是xy问题。有一些建议的方法可以使状态参数持久化,而问题位于这个表面之外。
根据问题的定义,数据应该独立于状态。所以这是一种与国家相关的全球性问题。因此,应该有一个服务来维护它,并且两种状态的控制器都需要维护它。只是不要在状态参数中传递超出某个状态作用域的数据。
Sticky状态很容易适应这种方法,因为它允许在另一个状态处于活动状态时保持DOM和$scope
。但是当状态被重新激活时,它与状态参数无关。
- 删除处于抽象状态的参数angular
- 使用应用程序状态js和视图在angular js url上传递两个参数
- angularjs-ui路由器父状态,参数加载在子状态之后
- Angularjs-ui路由器使用不同的参数进入相同的状态
- 否则用于具有类型化参数的状态
- 使用状态参数转换到不同的状态
- 如何将参数传递到 UI 路由器状态的模式窗口
- 如何同步Redux状态和url哈希标记参数
- 如何获取 ui 路由器状态参数
- 如何通过串联在视图中构造 AngularJS 状态参数
- 将状态参数传递给状态提供程序中设置的控制器
- 使用Angular ui路由器基于状态参数的负载控制器
- 如何在Aurelia路由器中定义状态参数
- 如何自动注入状态参数
- ui路由器deferIntercept和状态参数
- AngularJS将状态参数传递给data字段
- 重新加载页面时无法识别状态参数的Ui-router状态
- 如何在转换中获取下一个状态参数
- 如何在ui-router中持久化浏览器上的可选状态参数
- 在$urlRouterProvider (UI-Router)中插入子状态参数