我正在将使用类似 Oracle 表单的技术创建的大型 CRUD 业务应用程序移植到 Web(HTML5/AngularJS/RESTful-web-services)。
业务逻辑设置的部分方式取决于模式对话框的可用性,显示 CRUD 网格。首先,用户...
- 点击网格中的一行
- 在行的第一个字段中输入数据
- 按 Enter
- 光标被发送到右侧的下一个字段
- 等等
- 他们编辑其他字段,等等
- 他们点击页面上某处的“保存”
- 进行验证,调用网络服务 -> 数据已存储。
我已经通过 AngularUI 的 ng-grid 构建了该部分。
下一步是我绊倒的地方:
- 双击网格行,会出现一个新的 MODAL 对话框,显示“详细网格”。
- 您可以编辑/删除网格中的任何内容,也可以再次双击网格行,然后会出现另一个新的模态对话框,显示“详细信息网格”。等等。
当我通过 Angular UI 的 $dialog 服务尝试此操作时,我很快就遇到了障碍 - 嵌套 $dialog 的 (e.g. see this issue on the GitHub repos) 有很多问题。 ,更令人担忧的是,他们最近(2 个月前)决定简单地放弃旧的对话框,因为它有太多问题,and rewrite it from scratch .
我向其他 Angular 开发人员提出的问题是,你们如何处理嵌套模式对话框?您是否使用其他库 - 例如jQueryUI 的对话框?如果是这样,你如何“以 Angular 方式”使用它们?即不在 Controller 中混合 DOM 处理?我尝试follow the example of another SO question它确实有效,但它将对话框的 HTML 嵌入到页面的部分中 - 这不好(例如,想象一下必须在所有 Angular 中嵌入通过 F1 显示的帮助对话框的所有 HTML 代码(“显示键盘快捷键对话框”) HTML 模板部分!
我正在考虑通过 $http 加载对话框模板(就像 Angular UI 对话框一样)并通过 ngIninclude 注入(inject)内容,但这意味着我必须在 DOM 中为它们保留一个占位符('#dialogPlace' 或其他东西) ) - 由于我要处理的嵌套“深度”可能是无限的,恐怕我将不得不自己编写“堆栈处理”代码,一路添加 DOM 元素。天知道这本身会导致什么......
我真的很喜欢 Angular,但我的问题域需要一个用于嵌套模式对话框的可靠工作组件。我希望有人遇到过这个问题,并有一个干净的、类似 Angular 的解决方案......
最佳答案
由于无法通过“重建中”的 AngularUI 对话框服务来解决这个问题,所以我使用了 jQueryUI 的对话框(它没有模态生成模态生成模态的问题...),并创建了一种“迷你-我自己的框架”。我所做的很多工作都是基于 AngularUI 对话框的源代码,而且它似乎工作得很好。
这是我编码的 Angular 服务( typescript 代码,因此它有一些类型规范 - 但除此之外是纯 Javascript)。由于它将生成模式对话框,因此我将该服务称为“Plato”:-)
...
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
}
像往常一样使用 Angular Controller 和指令的 HTML 部分模板:
<div data-ng-controller="controllerMunicipalitiesLOV">
<div data-ng-grid="..."
...
模态对话框 Controller 具有如下处理程序:
var dialogOptions = $scope.$parent.dialogOptions;
$scope.close = function(result) {
dialogOptions.result.whatever = ....;
dialogOptions.jquiDialog.dialog("close");
dialogOptions.callback();
};
我基本上传递给showDialog:
- 调用者的范围,我在其中存储传递的“dialogOptions”
- 对话框标题
- 对话框的 HTML 模板
- “dialogOptions”,其中的内容在 .result 中的对话框中传递和传递
- “dialogOptions”还包含回调
这个设计是一个完整的黑客,温和地说,但它有效:我使用调用者的范围来存储dialogOptions,并且在对话框的 Controller 内,我使用$scope.$parent.dialogOptions,来读取传入的内容调用者,并存储回调将读取的任何结果(“dialogOptions”充当两个范围之间的桥梁)。
至少截至 2013 年 7 月,这是我发现/破解的唯一 Angular-y 方式来创建可以以嵌套方式生成的模式对话框(例如,controllerMunicipalitiesLOV Controller 依次调用 showDialog,另一个 Controller 调用再次,等等)。
我希望我知道一种将“dialogOptions”作为附加参数传递给模式对话框 Controller 的方法 - 不幸的是我不太熟悉 Angular 内部;非常欢迎任何帮助(这将使这个界面更加清晰)。
希望这对某人有帮助。
关于jquery-ui - AngularJS 嵌套模式对话框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18078233/