使用AngularJS ui路由器创建类似弹出窗口的状态

Creating a popup like state using AngularJS ui-router

本文关键字:窗口 状态 AngularJS ui 路由器 创建 使用      更新时间:2023-09-26

我试图创建一个类似弹出窗口的状态,即它不会清除当前状态,只是在不完全破坏当前状态的情况下弹出(这样用户就可以通过关闭弹出窗口来访问它)。

经过严格简化,我的应用程序路由如下:

angular.module('test', ['ui.router'])
  .config(['$stateProvider', '$urlRouterProvider',
    function($stateProvider, $urlRouterProvider) {
      $stateProvider
        .state('login', {
          url: '/login',
          template: '<button><a ui-sref="authenticated.home">Login</a></button>'
        })
        .state('authenticated', {
          url: '/authenticated',
          template: '<p>We are now authenticated</p>' +
            '<a ui-sref="authenticated.home">home</a>' +
            '<a ui-sref="authenticated.statistics">statistics</a>' +
            '<a ui-sref="authenticated.popup">Popup!</a>' +
            '<div ui-view></div>' +
            '<div ui-view="popup"></div>'
        })
        .state('authenticated.home', {
          url: '^/home',
          template: '<p>We are in home. <br><input></p>'
        })
        .state('authenticated.statistics', {
          url: '^/statistics',
          template: '<p>We are in statistics. <br><input></p>'
        })
        .state('authenticated.popup', {
          url: '^/popup',
          views: {
            popup: {
              template: '<div id="popup"><p>popup is up</p>' +
                '<a ui-sref="authenticated.home">close</a>' +
                '</div>'
            }
          }
        });
      $urlRouterProvider.otherwise('/login');
    }
  ]);
a {
  margin-right: 20px;
  text-decoration: none;
}
#popup {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 100%;
  background: #000;
  color: #fff;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.18/angular-ui-router.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>
<div ng-app="test">
  <div ui-view>
  </div>
</div>

  • 向用户显示登录屏幕
  • 登录后,用户将重定向到authenticated.home状态。经过身份验证的父状态包含导航菜单和<ui-view>以附加子视图
  • 用户可以使用此导航在应用程序周围导航到其他路线,如authenticated.statisticsauthenticated.popup

问题是,当我简单地移动到弹出状态时,即使我在它的视图对象中指定了popup视图,它也会清除其他ui-view(这是有道理的,因为我们不再处于与之匹配的状态)。

我能想到的一个解决方案是使用类似ui路由器的附加功能要返回到以前的状态,问题是用户在以前的状态中所做的任何更改都将丢失。

另一种解决方案是将弹出窗口的模板放在authenticated状态模板中并显示/隐藏它。但问题是,弹出窗口应该是一个可添加书签的状态,它根据状态参数从服务器加载数据。

有没有更好的方法来创建一个比当前状态更像弹出窗口的状态?也许是通过改变模板结构,或者使用一些我没有想到的抽象状态?

从ui路由器附加组件添加的粘性状态应该是您想要的。使您能够创建粘性/并行状态,因此它应该允许您在不影响原始状态的情况下创建弹出状态。

我还没有对它进行足够的实验来了解所有的细节,但主要的想法是将所有的主要状态转移到根应用程序状态下,并将粘性设置为真:

$stateProvider.state('app', {
      url: '',
      views: {
        'app': {
          templateUrl: 'app.html',
          controller: 'mainCtrl',
        }
      },
      sticky: true
  });
  $stateProvider.state('app.account', {
      url: '/account',
      templateUrl: 'account.html'
  });
  $stateProvider.state('app.account.stuff', {
      url: '/stuff',
      template: "<h3>Here's my stuff:</h3><ul><li>stuff 1</li><li>stuff 2</li><li>stuff 3</li></ul>"
  });

之后,将您的模态状态添加为同级(因此不是根应用程序状态的子级)

$stateProvider.state('modal', {
      url: '/modal',
      views: {
        'modal': {
          templateUrl: 'modal.html'
        }
      }
  });

我以文档中提供的示例为例,进行了一些编辑以添加控制器并简化它:http://plnkr.co/edit/4JGdIcDUQs0Za4fBaLj1?p=preview

听起来像是抽象状态可以修复的东西。

将"已验证"状态更改为抽象父状态并在其上附加一个控制器,可以允许axx数据由子状态转换。此外,您可以为数据制作一个单独的控制器,并在body标签上放置一个ng控制器。

如果您在实现方面仍然存在问题,那么使用LocalStorage来持久化您想要的数据怎么样?

Update2找到一个帖子,并在键入时更改了更新ng模型的plnk,但我明白OP为什么想要弹出窗口。

编辑Plnkr共享状态示例

我将尝试找到一个好的例子,但这里有一些伪代码。

.state('authenticated', {
      abstract: true,
      url: '/authenticated',
      controller: 'AuthStateController',
      template: '<p>We are now authenticated</p>' +
        '<a ui-sref="authenticated.home">home</a>' +
        '<a ui-sref="authenticated.statistics">statistics</a>' +
        '<a ui-sref="authenticated.popup">Popup!</a>' +
        '<div ui-view></div>' +
        '<div ui-view="popup"></div>'
    })

我认为,无论是否使用{abstract: true},您的弹出状态都应该可以访问"AuthStateController"内部的数据。解析的东西可能是一个过度的解决方案,但可能会让你知道如何更有效地使用控制器数据。。如果其他一切都失败了。。构建一个处理数据的服务。

.state('authenticated.popup', {
      url: '^/popup',
      views: {
        popup: {
          resolve: {
            ctrl: 'AuthStateController',
            data: function(ctrl) {
              return ctrl.data_for_popup;
            }
          }
          template: '<div id="popup"><p>popup is up</p>' +
            '<a ui-sref="authenticated.home">close</a>' +
            '</div>'
        }
      }
    })

您在主页面上查找的内容可能有所不同。您需要在index.html或基本模板上保留2个ui-view

然后在加载状态时执行以下操作:

 $stateProvider.state('stateNAme', {
                url: '/name',
                views: {
                    "main": {
                        controller: '1Controller',
                        templateUrl: 'tpl1.html'
                    },
                    "sidebar@": {
                        controller: '2Controller',
                        templateUrl: 'tpl2.html'
                    }
                }

阅读此处关于多个命名视图