如何在ui-router中保留浏览器上的可选状态参数?

时间:2015-07-21 15:10:24

标签: javascript angularjs angular-ui-router angular-ui angularjs-routing

我有一个父母州,里面有两个孩子的州,我将根据URL显示一个州。

在这两个states中有param1param2之类的参数,我在状态定义中使用了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
    }
});

如果你查看我的路线,URL内部并没有真正引入params选项,这就是为什么我认为这是可选的。

问题

看看plunkr,我已经显示了两个标签帐户& 调查

  1. 单击“调查”选项卡,然后在显示的textarea中添加一些数据。
  2. 点击转到帐户,将textarea值传递给 通过锚点

  3. 执行ui-sref="tabs.account({param1: thing1, param2: thing2})"其他帐户标签
  4. 现在您将看到param1& html上的param2值已从$stateParams

  5. 分配到范围
  6. 再次点击调查标签,您将登陆调查页面。
  7. 只需点击浏览器,您就会发现param值未获得null
  8. Problem Plunkr

    我相信你得到了我想问的问题,为什么可选参数值没有存储?因为他们是国家的一部分。

    我知道我可以通过以下两种解决方案来解决这个问题。

    • 创建一个将在两个视图之间共享数据的服务。
    • 通过在状态URL中添加参数。比如url: '/account/:param1/:param2',(但我不会喜欢这个)

    我已经尝试过angular-ui-routers sticky states,但这对我来说似乎不起作用。有什么更好的方法呢?

    有什么方法可以让我的用例工作,任何想法都会很感激。

    Github Issue Link Here

4 个答案:

答案 0 :(得分:20)

我会将params定义移动到父状态,以便在两个子状态之间共享可选的状态参数。

子状态将从您的父级继承$stateParams,因此不需要真正的“解决方法”。

只需按照惯例在您的孩子控制器中注入$stateParams,您就可以完全访问被传递的参数。如果您不想在特定的子状态下使用params,只需避免注入它们。

这适用于;

  • 后退按钮
  • 转发按钮
  • ui-sref (没有参数(将保持原样))
  • ui-sref (使用params(将覆盖))
$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的状态树内旅行时想要清除这些参数,则必须手动执行

这将是我通过使用此解决方案可以看到的唯一真实警告。

我知道在您出席的情况下可能不希望手动清算,但您没有采取积极的立场反对它,因此我觉得这个建议是有价值的。

<强> updated plunker

答案 1 :(得分:7)

一个解决方法解决方案是缓存状态参数并在进入<html> <head> <script type='text/javascript'> window.addEventListener('load', function(){ var embed = document.getElementsByName('plugin')[0]; // this method should return the page location (not the page number, i suppose that made some calculation on the portion of PDF that is showed in the embed window) alert(embed.getPageLocationNormalized()); // we can use other api methods embed.removePrintButton(); }, false); </script> </head> <body marginwidth='0' marginheight='0' style='background-color: rgb(38,38,38)' width='100%' height='100%'> <embed width='100%' height='100%' name='plugin' src='path_to_pdf_file' type='application/pdf' /> </body> </html> 状态时有条件地加载它们。 UI路由器状态配置实际上允许您为这些类型的“在进入状态时执行某些操作”情况提供tabs.account回调。

以下是使用localStorage作为缓存的基本逻辑,使用了Plunker here

  • 当您进入onEnter状态时,请检查您的州参数
    • 如果您有,请将它们缓存到本地存储
    • 如果不这样做,请将它们从本地存储装入tabs.account

以下是一个示例代码片段供参考(取自Plunker):

$stateParams

一个警告是你的参数将无限期地持续存在(例如,刷新和会话)。要解决这个问题,您可以清除应用程序加载中的缓存,如 $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'); } }], ... }

最后一点是,在Plunker中,我正在直接访问本地存储(通过Angular app.run服务)。您可能想要使用一些AngularJS模块 - 我在生产中使用了angular-local-storage

答案 2 :(得分:2)

我相信如果不使用您提供的两种解决方案之一,您无法实现的目标。

浏览器后退按钮只保留URL历史记录。他对ui-router内部状态一无所知,只会强制更改URL。

强制更改URL将触发内部ui-router机器,但不幸的是ui-router会看到URL改变,就像有人会手动更改URL一样。

Ui-router将触发新路由更改到URL指向的路由。这意味着他并不知道你想要回去&#34;并且只会在没有任何参数的情况下将状态更改为新状态。

<强>摘要

单击后退按钮将根据URL将状态更改激活到状态,而不是返回到先前的状态。

这就是为URL添加params解决问题的原因。由于URL具有歧视性,因此您最终会落在您想要的状态。

希望它有所帮助。

答案 3 :(得分:0)

对我而言,这听起来像X Y problem。有建议的方法使状态参数持久,而问题是在这个表面之外。

根据问题的定义,有些数据应该独立于国家。所以这是一种全球性的相对于国家。因此应该有一个服务来保持它和两个州的控制器按要求维护它。只是不要在状态参数中传递超出一个状态范围的数据。

粘性状态很容易适合这种方法,因为它允许在另一个状态处于活动状态时保留DOM和$scope。但是当国家重新启动时,它与国家参数无关。