关闭模态对话框时调用函数的数据属性

时间:2017-09-19 14:53:34

标签: angularjs twitter-bootstrap event-handling modal-dialog

我正在使用Bootstrap与AngularJS一起打开模态对话框。要在不编写JavaScript代码的情况下激活模态,我会使用documentation中所述的数据属性。这是一种非常方便的方法,因为我不需要手动显示/隐藏对话框。

<button type="button" data-toggle="modal" data-target="#myModal">Launch modal</button>

现在我想在关闭模态对话框时调用一个方法。使用显式关闭按钮,这没有问题。但是,当用户点击对话框外部或按 Esc 键时,我无法明确触发任何功能。

我知道我可以使用jQuery或Angular的$uibModal来监听dismiss事件,但这会使整个项目变得更加复杂。我宁愿把它放在一个地方。我不想混淆,所以在我的AngularJS项目中使用jQuery不是一个选项。我现在坚持使用的解决方案是手动使用$uibModal open()对话框并捕获结果以处理用户调用的解雇。

我的问题:

  

如果关闭模态对话框而不引入太多混乱,如何调用函数?

我的想法是这样的(虚构的data-dismiss-callback):

<button type="button" data-toggle="modal"
                      data-target="#myModal"
                      data-dismiss-callback="handleCloseEvent()">Launch modal</button>

1 个答案:

答案 0 :(得分:1)

由于我们希望使用打开它的按钮将指定行为(自定义回调)附加到目标模态,因此directive是帮助我们实现此目标的最佳候选者。

我们将听show.bs.modal and hide.bs.modal/hidden.bs.modal events:第一个将帮助我们确定是否使用相应的按钮打开模态,第二个是我们想要调用传递的回调函数的地方。

以下是modalDismissCallback指令(due to normalization的工作示例,我们无法将其命名为dataDismissCallback):

angular.module('myDemoApp', [])
    .controller('myCtrl', [function () {
        var ctrl = this;
        ctrl.testVar = 2;
        ctrl.onModalDismiss = onModalDismiss;

        function onModalDismiss(a, e) {
            console.log(arguments);
        }

        return ctrl;
    }])
    .directive('modalDismissCallback', [function modalDismissCallback() {
        return {
            restrict: 'A',
            scope: {
                modalDismissCallback: '&'
            },
            link: function (scope, element) {
                var modal = angular.element(element.data('target'));

                modal.on('show.bs.modal', onShow);
                modal.on('hide.bs.modal', onHide);

                scope.$on('$destroy', function () {
                  modal.off('show.bs.modal', onShow);
                  modal.off('hide.bs.modal', onHide);
                });
                
                var shouldCall = false;

                function onShow(e) {
                    shouldCall = e.relatedTarget === element[0];
                }

                function onHide(e) {
                    if (angular.isFunction(scope.modalDismissCallback) && shouldCall) {
                        scope.$event = e;
                        scope.$applyAsync(function () {
                            scope.modalDismissCallback.apply(this, arguments);
                        });
                    }
                }
            }
        }
    }]);
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta.3/css/bootstrap.min.css">

<body ng-app="myDemoApp">

<div ng-controller="myCtrl as $ctrl">

    <button type="button" class="btn btn-default"
            data-toggle="modal"
            data-target="#myModal"
            modal-dismiss-callback="$ctrl.onModalDismiss($ctrl.testVar, $event)">Launch modal
    </button>
    
    <button type="button" class="btn btn-default"
            data-toggle="modal"
            data-target="#myModal">Launch modal wo callback
    </button>

    <div id="myModal" class="modal fade bd-example-modal-sm" tabindex="-1" role="dialog"
         aria-labelledby="mySmallModalLabel" aria-hidden="true">


        <div class="modal-dialog" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <h4 class="modal-title" id="myModalLabel">Modal title</h4>
                </div>
                <div class="modal-body">
                    <div ng-include="'template.html'"></div>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                </div>
            </div>
        </div>

    </div>
</div>

<script type="text/ng-template" id="template.html"><h5>Hello from ng-template!</h5></script>
</body>




<script type="text/javascript" src="//code.jquery.com/jquery-3.1.1.slim.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta.3/js/bootstrap.min.js"></script>