带角度的模态窗口(UI-Router/Directive)

SDe*_*kov 8 javascript twitter-bootstrap angularjs angular-ui-router

我花了一些时间来研究一种控制模态窗口的通用方法,AngularJS并且所提出的选项都不是"好"解决方案.

指令解决方案

我找到了这个演示,但是缺点是你必须手动管理和存储模态的状态并跨范围更新它:

scope.$parent[attrs.visible] = true;
Run Code Online (Sandbox Code Playgroud)

此外,如果您必须添加更多功能,例如实际添加带有弹出窗口的项目,这将涉及父页面范围上更难看的代码.

UI路由器解决方案

这是关于如何使用ui路由器的模态的官方指南.

然而,这是使用ui.bootstrap.modal

我的问题是,是否有任何简单而优雅的解决方案,坦率地说这是一个非常简单的问题......

像这样的东西例如:

.state('popup', {
        url: '/item/add/',
        views: {
            'popupView': {
                templateUrl: "/myPopup.html",
                controller: "myPopupController"
            }
        },
        type: 'modal'
    })
Run Code Online (Sandbox Code Playgroud)

关闭,重定向,提交等所有内容都在处理中myPopupController.

我不是要解释为什么上面的例子是这样的,或者我应该如何使用它们.我只想看看是否有人提出了更好的解决方案.

小智 4

我已经在 ui-router 的模态/对话框插件上工作了一段时间(利用它和 ui-router-extras)。

我正在将一些内部代码移植到开源项目中,如果您愿意尝试的话,这将是一个巨大的好处(对我来说当然如此)。

我们目前在生产应用程序中使用内部版本,并且运行良好。我的目标是让开源版本在消费者 API 和性能方面变得更好。

配置阶段

var app = angular.module('mod', ['angular.ui.router.modal', /** ui-router + ui-router-extras **/]);

app.config(function ($uiRouterModalProvider) {
  $uiRouterModalProvider.config({
    viewName: 'my_modal_view_name',
    templateUrl: '/path/to/my_modal_wrapper.html',
    rootState: 'name_of_my_apps_root_state',
    controller: 'my_modal_wrapper_controller',
    resolve: {
      common: function ($http) {
        return $http.get(apiUrl + '/common_modal_settings');
      }
    }
  });
});
Run Code Online (Sandbox Code Playgroud)

让我们来看看不同的部分:

视图名称

这是您的模态模板将驻留在其中的名称ui-view。您的页面中需要有一个容器,其属性指向位于常规内容ui-view旁边的视图(示例将在稍后显示)。$uiRouterModalProvider.viewNameui-view

该包提供了一个指令来为您执行此操作

模板网址

这是所有模态框的基础。假设您想要一个具有某些属性的容器,并且$scope在任何给定时间点都独立于模态的内部内容。

根状态

这是应用程序中根状态的名称。重要的是,它与保存根 ui-view元素和模态元素的状态相匹配ui-view

控制器

通用模态控制器的名称。也可以是一个函数(尽管我总是推荐一个可以单独进行单元测试的命名控制器)。

解决

每个模式的公共解析块。这与每个模式状态自己的解析块相互依赖。有关解析的 API 和行为仍在不断变化。


国家登记阶段

现在已经配置了基本行为,这就是注册模态状态的方式:

.modalState('home.mySuperModal', {
  url: '/my-super-modal',
  templateUrl: 'superModal.html',
  controller: 'SuperModalController'
});
Run Code Online (Sandbox Code Playgroud)

.modalState函数将注册一个状态并引用 modalProvider 中设置的通用设置,并将给定的状态定义转换为最终状态对象,如下所示:

.state('home.mySuperModal', {
  url: '/my-super-modal',
  views: {
    'modal_view_name@root_state': {
      templateUrl: 'modal_wrapper.html',
      controller: 'ModalWrapperController'
    }
  },
  $$originalState: {
    templateUrl: 'superModal.html',
    controller: 'SuperModalController'
  }
});
Run Code Online (Sandbox Code Playgroud)

标记

<!-- The outermost ui-view element -->
<html>
  <body ng-app="app">
    <div ui-view></div>
  </body>
</html>

<!-- The content for the root state of your application {living inside the outermost ui-view directive} -->
<div>
  <ui-view></ui-view>
  <ui-modal-view></ui-modal-view>
</div>
Run Code Online (Sandbox Code Playgroud)

现在我们的模态包装器的容器已设置完毕。但里面的内容呢?

这是另一个指令发挥作用的地方;uiModalFill。这需要出现在您的包装模式模板中。像这样:

<!-- wrapping modal template -->
<div id="modal_wrapper">
  <h1>Some heading. I'm always present!</h1>

  <hr>

  <ui-modal-fill></ui-modal-fill>
</div>
Run Code Online (Sandbox Code Playgroud)

结论

如果您想尝试一下,请先做一些最后的说明:

  • 许多所需的功能尚未移植/实现。就目前而言,这是一项正在进行的工作。
  • 一些 API 很可能在不久的将来发生变化,包括但不限于属性resolve以及 $state.resolve 与通用 modal.resolve 一起存在的方式。
  • 一些样板要求需要更改。API 应该易于使用(但又灵活),但现在消费者必须填写太多细节。
  • 该文档实际上不存在。弄清楚幕后实际情况的最佳方法是查看源代码(抱歉......)。

所以,如果我没有成功吓退你,请前往 GitHub 并获取angular-ui-router-modal并尝试一下。如果您需要任何帮助,我随时可以在 GitHub 和/或 SO 上找到我。

或者如果您只是想缠着我写一些文档。我完全理解这一点。