2

我正在将使用类似 Oracle 表单的技术创建的大型 CRUD 业务应用程序移植到 Web(HTML5 / AngularJS / RESTful-web-services)。

设置业务逻辑的部分方式取决于模式对话框的可用性,显示 CRUD 网格。首先,用户...

  • 单击网格的一行
  • 在行的第一个字段中输入数据
  • 按 ENTER
  • 光标被发送到右侧的下一个字段
  • 等等
  • 他们编辑其他字段,依此类推
  • 他们点击页面某处的“保存”
  • 发生验证,调用 Web 服务 -> DATA STORED。

我已经通过 AngularUI 的 ng-grid 构建了该部分。

下一步是我偶然发现的地方:

  • 双击网格的行,会出现一个新的 MODAL 对话框,显示“详细网格”。
  • 您可以从网格中编辑/删除/等任何内容,也可以再次双击网格行,然后会出现另一个新的 MODAL 对话框,显示“详细信息网格”。等等。

当我通过 Angular UI 的 $dialog 服务尝试这个时,我很快就遇到了墙 - 嵌套的 $dialog 有很多问题(例如,在 GitHub 存储库上查看这个问题),更令人担忧的是它们最近(2 个月前)决定干脆放弃旧对话框,因为它有太多问题,并从头开始重写

我对任何 Angular 开发人员的问题是,你如何处理嵌套的模态对话框?您是否在使用其他库 - 例如 jQueryUI 的对话框?如果是这样,您如何“以 Angular 方式”使用它们?即没有在您的控制器中混合 DOM 处理?我尝试按照另一个 SO question 的示例进行操作,并且确实有效,但是它将对话框的 HTML 嵌入到页面的部分中-这不好(例如,想象必须为通过 F1 显示的帮助对话框嵌入所有 HTML 代码(“在所有 Angular HTML 模板部分中显示键盘快捷键对话框”)!

我正在考虑通过 $http 加载对话框模板(如 Angular UI 对话框)并通过 ngInclude 注入内容,但这意味着我必须在我的 DOM 中为它们保留一个占位符('#dialogPlace' 或其他东西) - 和由于我有可能无限的嵌套“深度”来处理,恐怕我将不得不自己编写“堆栈处理”代码,一路添加 DOM 元素。天知道这本身会导致什么...

我真的很喜欢 Angular,但我的问题域需要一个用于嵌套模式对话框的可靠工作组件。我希望有人遇到过这个问题,并且有一个干净的、类似 Angular 的解决方案......

4

3 回答 3

2

由于无法使用“正在重建”的 AngularUI 的对话框服务来解决这个问题,我使用了 jQueryUI 的对话框(它没有任何关于模态生成模态的问题......),并创建了一种“迷你框架”我自己的。我所做的很多工作都是基于 AngularUI 对话框的来源,它似乎工作正常。

这是我编写的 Angular 服务(打字稿代码,所以它有一些类型规范 - 但不是纯 Javascript)。由于它会产生模态对话框,我将服务称为“柏拉图”:-)

...

export function addNewServices(application:ng.IModule) {
    application.factory('Plato', ['$http', '$compile', function($http, $compile) {
        return {
            showDialog: function(scope, strTile:string, templateUrl:string, dialogOptions, callback) {
                scope.dialogOptions = dialogOptions;
                scope.dialogOptions.callback = callback;
                $http.get(
                    templateUrl,
                    {timeout:globals.timeoutInMs, cache:false}
                ).success(function(response, status, header, config) {
                    var newDialogId = Sprintf.sprintf("npInnerDlg%d", globals.dialogCounter);
                    globals.dialogCounter += 1;
                    var modalEl = angular.element('<div id="' + newDialogId + '">');
                    modalEl.html(response);
                    $('body').append(modalEl);
                    $compile(modalEl)(scope);
                    var component = $('#' + newDialogId);
                    scope.dialogOptions.jquiDialog = component;
                    component.dialog({
                        autoOpen:false,
                        modal:true,
                        title:strTile
                    });
                    component.dialog("open");
                }).error(function(data, status, header, config) {
                    document.body.style.cursor  = 'default';
                    if (status == 406) {
                        console.log("Received 406 for:" + header + " # " + config);
                        alert("Received 406 from web service...");
                    } else {
                        console.log("Status:" + status);
                        console.dir(config);
                        alert("Timed-out waiting for data from server...");
                    }
                });

            }
        };
    }]);
}

...并像这样使用它:

首先,要显示对话框的调用代码:

var dialogOptions = {
    callback: function() {
        if (dialogOptions.result !== undefined) {
            cust.mncId = dialogOptions.result.whateverYouWant;
        }
    },
    result: {}
};

Plato.showDialog(
    $scope,
    'Choose something...',
    '/static/partials/municipalityLOV.html',
    dialogOptions
}

像往常一样使用角度控制器和指令的 HTML 部分模板:

<div data-ng-controller="controllerMunicipalitiesLOV">
    <div data-ng-grid="..."
    ...

和模态对话框控制器具有这样的处理程序:

var dialogOptions = $scope.$parent.dialogOptions;
$scope.close = function(result) {
    dialogOptions.result.whatever = ....;
    dialogOptions.jquiDialog.dialog("close");
    dialogOptions.callback();
}; 

我基本上传递给showDialog:

  • 调用者的范围,我存储传递的“dialogOptions”
  • 对话框标题
  • 对话框的 HTML 模板
  • .result 中的对话框传入和传出内容的“dialogOptions”
  • “dialogOptions”还包含一个回调

委婉地说,这个设计是一个完整的 hack,但它确实有效:我使用调用者的范围来存储 dialogOptions,在对话框的控制器中,我使用 $scope.$parent.dialogOptions 来读取来自调用者的传入内容,并存储回调将读取的任何结果(“dialogOptions”充当两个范围之间的桥梁)。

至少截至 2013/7 月,这是我发现/破解的唯一 Angular-y 方式来创建可以以嵌套方式生成的模态对话框(例如,controllerMunicipalitiesLOV 控制器依次调用 showDialog,另一个控制器再次调用它, ETC)。

我希望我知道一种将“dialogOptions”作为附加参数传递给模态对话框控制器的方法 - 不幸的是,我并不精通 Angular 内部;最欢迎任何帮助(它会使这个界面更干净)。

希望这可以帮助某人。

于 2013-08-07T12:24:08.033 回答
1

我们使用http://angular-ui.github.io/bootstrap/#/modal作为我们的模态。

我们基本上在这里列出了相同的问题。带有绑定数据的大网格,编辑按钮以调出模式,删除,保存等。

您只会在页面上隐藏一个模态 div,然后在单击时传入网格行模型(这很痛苦)。

例如

$scope.editRow = function (model) {
   // do stuff.
};

<span class="icon-edit" ng-click="editRow(model.row)">Edit</span>

在字段中通过所有 ng-click/controller 方法传递对象只是让模态工作,这很奇怪,但它最终解决了并且是 DRY。

不确定这是否有帮助。

于 2013-08-06T15:39:48.123 回答
0

为同样的问题而苦苦挣扎,我将各个部分放在一起,构建sgDialogService。这是一个小型模块服务,允许多个嵌套对话框/警报/确认,其语法类似于标准 Angular 对话框:

var modalInstance = sgDialogService.openModal({
        templateUrl:'sample/dialogContent.html',
        controller:"sampleController",
        data:{fromParent:dialogParam},
         callback: function(result){ $scope.callbackResult=result;}
    });
}

这个想法是

  • 对所有对话框使用一个模板(基于引导程序)
  • 避免与 Angular 和标准 Javascript 以外的任何连接
  • 在 $controller 和 $compile 服务的支持下动态构建和编译内部视图
  • 允许在不创建新范围的情况下使用对话框(whit or)
  • 最后拖动对话框(没什么奇怪的,但似乎是互联网上的一个主要问题。

尽快我会在 github 上放一个版本......只需要添加单元测试

编辑 1

在 github 上设置存储库:sgDialogService

于 2015-04-20T16:26:18.393 回答