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

时间:2015-07-14 12:15:28

标签: javascript angularjs twitter-bootstrap angular-ui-router

我现在花了一些时间研究一种用AngularJS来控制模态窗口的通用方法,并且所提出的选项都没有任何附近好的'溶液

指令解决方案

我发现了this演示,但是缺点是你必须手动管理和存储模态和跨范围更新它的状态:

scope.$parent[attrs.visible] = true;

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

UI路由器解决方案

This is the official guide on how to use modals with ui router.

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

我的问题是,对于一个非常简单的问题,是否有任何简单而优雅的解决方案......

例如:

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

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

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

3 个答案:

答案 0 :(得分: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');
      }
    }
  });
});

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

的viewName

这是您的模态模板所在的ui-view的名称。您需要在页面中有一个容器,其ui-view属性指向{{1}的视图与您的常规内容{/ 1}}相邻(示例将在稍后显示)。

该软件包提供了一个指令,可以为您执行此操作

templateUrl

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

rootState

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

控制器

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

决心

每个模态的通用解析块。这与每个模态状态自己的解析块相互依赖。 关于做出决议的API和行为仍在不断变化。

州注册阶段

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

ui-view

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

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

标记

.modalState

现在设置了模态包装器的容器。 但内心的内容呢?

这是另一个指令发挥作用的地方; .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' } }); 。这需要出现在包装模式模板中。就这样:

<!-- 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>

结论

之前的一些最后的注释(如果)你想要这样做:

  • 许多所需功能尚未移植/实施。这是一项正在进行中的工作。
  • 有些API可能会在不久的将来发生变化,包括但不限于uiModalFill属性以及$ state.resolve与常见modal.resolve共存的方式。
  • 某些样板要求需要更改。 API应该易于使用(但是很灵活),但是现在消费者必须填写太多细节。
  • 文档实际上不存在。找出幕后实际的最佳方法是查看来源(抱歉......)。

所以,如果我没有成功地吓跑你,那就去看看GitHub并抓住 angular-ui-router-modal 搏一搏。如果您需要任何帮助,我可以在GitHub和/或SO上随时使用。

或者,如果你想纠缠于编写一些文档。我完全理解这一点。

答案 1 :(得分:0)

很好地显示一个指令并不是通过指令以声明方式很好地完成的。通过路由器/状态处理的解决方案也不是我个人所做的。

我的方法是使用Angular Service处理模态。通过服务,您可以强制打开您的模态。

您已经提到ui.bootstrap.modal,我认为这是一个非常好的解决方案。但它也非常灵活。

我使用方法dialogService创建了一个简单的openConfirmDialog,它有自己的控制器:

(function() {
    'use strict';

    angular.module('app').factory('dialogService', dialogService);

    function dialogService($modal) {
        return {
            openConfirmDialog: openConfirmDialog
        };

        function openConfirmDialog(texts, props) {
            texts = texts || {};
            texts = angular.extend({
                title: '',
                okText: 'Yes',
                cancelText: 'No',
                bodyText: ''
            }, texts);

            props = props || {};
            props = angular.extend({
                okClass: 'btn-primary',
                cancelClass: 'btn-default'
            }, props);

            return $modal.open({
                templateUrl: 'dialogconfirm.html',
                controller: ConfirmController,
                controllerAs: 'vm',
                resolve: {
                    texts: function() {
                        return texts;
                    },
                    props: function() {
                        return props;
                    }
                }
            }).result;
        }

        function ConfirmController($modalInstance, texts, props) {
            var vm = this;
            vm.texts = texts;
            vm.props = props;

            vm.ok = function() {
                $modalInstance.close();
            };

            vm.cancel = function() {
                $modalInstance.dismiss();
            };
        }
    }
}());

这可以直接在我的控制器中使用:

  vm.openDialog = function() {
    dialogService.openConfirmDialog({
      bodyText: 'Do you really want to close me'
    });
  };

这是一个有效的Plunker

使用此解决方案,我不必使用模型代码污染我的控制器和/或HTML视图。模态代码封装得非常好。

答案 2 :(得分:0)

您是否查看了AngularStrap http://mgcrea.github.io/angular-strap/#/modals

您可以传入x[2,2] <-1,您可以将控制器绑定到模态实例,从而为您提供完全控制(通过在模态模板的顶级元素上设置y <- x)。 / p>

您可以通过templateUrl以编程方式触发模态,或使用ng-controller="ModalCtrl"指令在html中设置属性。

http://plnkr.co/edit/h9BwU0dFTTdw59b6oTWv?p=preview