AngularJS嵌套模式对话框

时间:2013-08-06 10:55:57

标签: jquery-ui angularjs modal-dialog angular-ui

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

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

  • 点击网格的一行
  • 将数据输入行的第一个字段
  • 点击ENTER
  • 将光标发送到右侧的下一个字段
  • 他们编辑其他字段,依此类推
  • 他们点击页面上某处的“保存”
  • 验证发生,称为Web服务 - >数据存储。

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

下一步是我跌跌撞撞的地方:

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

当我通过Angular UI的$ dialog服务尝试此操作时,我很快遇到了墙壁 - 嵌套的$ dialog (e.g. see this issue on the GitHub repos)存在许多问题,更令人担心的是,他们最近(2个月前)决定只是放弃旧的对话框,因为它有太多问题,and rewrite it from scratch

我对任何Angular开发者的问题是,你是如何应对嵌套模态对话框的?你在使用其他的库 - 例如jQueryUI的对话框?如果是这样,你如何“以角度方式”使用它们?即在控制器中没有混合DOM处理?我尝试follow the example of another SO question并且确实有效,但是它将对话框的HTML嵌入到页面的部分中 - 这是不好的(例如,想象必须嵌入通过F1显示的帮助对话框的所有HTML代码(“显示键盘所有Angular HTML模板部分中的快捷方式对话框“)

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

我非常喜欢Angular,但我的问题域需要一个可靠的工作组件来嵌套模式对话框。我希望有人在那里遇到问题并且有一个干净的,类似角度的解决方案......

3 个答案:

答案 0 :(得分:2)

由于没有办法与“下重建” 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
}

使用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模板
  • “dialogOptions”,其中的内容传递给.result
  • 中的对话框
  • “dialogOptions”还包含回调

设计是一个完整的黑客,说得温和,但它的工作原理:我使用调用者的范围存储dialogOptions,并在对话框的控制器中,我使用$ scope。$ parent.dialogOptions,来读取来自的东西调用者,并存储回调将读取的任何结果(“dialogOptions”充当两个范围之间的桥梁)。

至少为2013 /月的,它是唯一的角-Y方式我发现/黑客攻击,以创建可以以嵌套的方式产生了(一个模态对话框例如controllerMunicipalitiesLOV控制器调用的ShowDialog反过来,和另一个控制器主叫它再次等。)

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

希望这有助于某人。

答案 1 :(得分:1)

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

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

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

e.g。

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

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

在通过所有ng-click /控制器方法传递对象的字段只是获得模态工作,这很奇怪,但它最终成功并且是干的。

不确定这是否有用。

答案 2 :(得分:0)

努力解决同样的问题,我把它放在了各个部分,构建sgDialogService。这是一个小模块服务,允许使用类似于标准Angular对话框的语法进行多个嵌套对话框/警报/确认:

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

想法是

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

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

修改1

在github上设置存储库:sgDialogService