【问题标题】:UI Router conditional ui views?UI 路由器条件 ui 视图?
【发布时间】:2013-10-17 14:34:08
【问题描述】:

我想不出一个合理的方法来解决这个相当琐碎的问题。

我希望访客在访问网站索引时看到启动页面,并希望登录用户看到他们的个人资料,每个页面都有自己的模板和控制器。 理想情况下,一个 url 会有两种状态,不知何故,我可以根据登录状态自动更改活动状态。这两个视图都有自己的嵌套视图,因此不能使用 ng-include(我假设)。

我对 angular 和 ui 路由器很陌生,我认为我可能忽略了一个简单的问题解决方案。

是否可以使用命名视图和 ng-show 来完成?

【问题讨论】:

  • 为什么不只是一个条件 ng-include?如果已登录则显示一个包含,如果未登录则显示另一个
  • “这两个视图都有自己的嵌套视图,因此不能使用 ng-include(我假设)。” ..找不到像 ui-router 中内置的 ng-include 之类的东西,或者它是否可以使用嵌套视图/某种解决方法?

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


【解决方案1】:

如果您使用的是 UI 路由器,只需创建三个状态:根状态,带有 '/' URL,以及两个没有 URL 的直接后代状态。在根状态的onEnter 中,您检测用户的状态并相应地转换到正确的子状态。这看起来为两个子状态保持相同的 URL,但允许您必须使用单独的配置来分隔状态。

【讨论】:

  • 我似乎无法在 onEnter 函数中使用 transitionTo?
  • 您可能需要检查$state.current 的值来验证您没有执行任何循环操作,因为onEnter 将始终触发您的根状态,即使在进入子状态时也是如此。
  • 我似乎无法从 onEnter 函数内转换到任何状态,包括不是我家乡状态的子状态。我可以在控制器中执行此操作,但不幸的是,这要等到所有内容都加载并显示在屏幕上才能运行。
  • 因为直到所有的解析和所有onEnter/onExit钩子都没有错误地执行后,转换才被认为是完成的,此时$state全局变量被更新。
  • 举个例子怎么样?这个答案没用,大家可以google一下,看文档。
【解决方案2】:

templateUrl 也可以是一个函数,因此您可以检查登录状态并返回不同的视图并在视图中定义控制器,而不是作为状态配置的一部分

【讨论】:

    【解决方案3】:

    我的解决方案:

    angular.module('myApp')
    .config(function ($stateProvider) {
        $stateProvider
            .state('main', {
                url: '/',
                controller: function (Auth, $state) {
                    if (someCondition) {
                        $state.go('state1');
                    } else {
                        $state.go('state2');
                    }
                }
            });
    });
    

    其中状态 1 和状态 2 在别处定义。

    【讨论】:

      【解决方案4】:

      出于文档目的,我使用了:

      $rootScope.$on('$stateChangeStart', function(event, toState) {
        if ((toState.name !== 'login') && (!$localStorage.nickname)) {
          event.preventDefault();
          $state.go('login');
        }
      });
      

      使用$routeChangeStart 对我不起作用。

      【讨论】:

      【解决方案5】:

      它用于我在ui-route中的条件视图

      $stateProvider.state('dashboard.home', {
              url: '/dashboard',
              controller: 'MainCtrl',
             // templateUrl: $rootScope.active_admin_template,
              templateProvider: ['$stateParams', '$templateRequest','$rootScope', function ($stateParams, templateRequest,$rootScope) {
                var templateUrl ='';
                if ($rootScope.current_user.role == 'MANAGER'){
                  templateUrl ='views/manager_portal/dashboard.html';
                }else{
                  templateUrl ='views/dashboard/home.html';
                }
                return templateRequest(templateUrl);
              }]
            });
      

      【讨论】:

        【解决方案6】:

        如果我理解了这个问题;您想确保尚未登录的用户看不到需要登录的页面。正确吗?

        我已经在控制器中使用了这样的代码:

        if(!'some condition that determines if user has access to a page'){
         $location.path( "/login" );
        }
        

        【讨论】:

        • 以 facebook 为例 - 如果访客访问 facebook 主页 (facebook.com),他们会看到一个启动页面,如果用户之前登录过,他们可以通过该页面登录或注册访问同一页面时,会显示他们的个人资料。我希望通过使用状态为登录用户和访客获取相同的 URL,因为配置文件页面将具有嵌套视图(将通过 url 更改访问)。我认为问题标题并没有很好地描述我想要什么!
        • @RyanConnolly 据我了解,Angular $routePovider 的全部目的是根据 URL 变量显示不同的元素/页面。我假设 [但不知道] Facebook 正在服务器端这样做。 If user is logged in; show wall else show login screen
        • 我想我需要帮助想一个聪明的方法来解决这个限制!我可以想出一些粗略的方法来做到这一点,但它们看起来都很老套,我不确定在实践中它们是否会起作用。
        【解决方案7】:

        在任何地方(可能在某些高级控制器中)您都应该能够将'$routeChangeStart' 事件绑定到$rootScope 然后进行检查:

        $rootScope.$on('$routeChangeStart', function(next, current){
            if(next != '/login' && !userLoggedIn){
                $location.path( "/login" );
            }
        });
        

        每次设置新路由时都会触发此事件,即使是在第一次访问页面时也是如此。

        【讨论】:

        • 我希望在不更改 url 的情况下实现它 - 这可能吗?
        • 所以你想在不改变url的情况下显示登录页面?就像在模态中一样?如果您想更改整个 ng-view 部分,那么您可能必须更改 url 以便更新 $routeProvider 并触发 $routeChange* 事件...
        • 仅供参考,请使用过渡挂钩而不是 $stateChangeStart$stateChangeSuccess。来源:ui-router.github.io/guide/ng1/…
        【解决方案8】:

        我这样做的方法很简单。我为我们的 A/B 测试策略做了一个。这是要点:

        resolve: {
           swapTemplate: function(service) {
              // all of this logic is in a service
              if (inAbTest) {
                 this.self.templateUrl = '/new/template.html';
              }
           }
           ... other resolves
        }
        

        这会在模板下载之前调用,因此您可以换出模板 url。

        【讨论】:

          【解决方案9】:

          在我的例子中,如果两个状态可以共享同一个控制器的逻辑,条件模板是一个不错的选择。否则,创建单独的状态是一个不错的选择。

          【讨论】:

            猜你喜欢
            • 2014-10-24
            • 1970-01-01
            • 1970-01-01
            • 2016-10-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多