Angular UI Bootstrap Modal - 如何防止多个模态打开

时间:2021-09-17 11:02:46

I've implemented the modal directive, and set the $modal.open option backdrop to false. However, now I can trigger multiple modals to open. Is there a way to prevent the trigger button from firing once one modal is open?

我已经实现了模态指令,并将$ modal.open选项背景设置为false。但是,现在我可以触发多个模态打开。有一种方法可以防止触发按钮在一个模态打开后触发吗?

var accountSummaryCtrl = function ($scope, $modal, $log) {

    $scope.open = function () {

        var modalInstance = $modal.open({
            templateUrl: '/Apps/generic/modal/Templates/AccountSummary.html',
            controller: ModalInstanceCtrl,
            backdrop: false
        });

        modalInstance.result.then(function (selectedItem) {
            $scope.selected = selectedItem;
        }, function () {
            $log.info('Modal dismissed at: ' + new Date());
        });
    };
};

Thanks

3 个解决方案

#1


12  

Use a boolean flag to avoid it:

使用布尔标志来避免它:

var accountSummaryCtrl = function ($scope, $modal, $log) {

    var opened = false;

    $scope.open = function () {

        if (opened) return;

        var modalInstance = $modal.open({
            templateUrl: '/Apps/generic/modal/Templates/AccountSummary.html',
            controller: ModalInstanceCtrl,
            backdrop: false
        });

        opened = true;

        modalInstance.result.then(function (selectedItem) {
            $scope.selected = selectedItem;
            opened = false;
        }, function () {
            $log.info('Modal dismissed at: ' + new Date());
            opened = false;
        });
    };
};

#2


0  

I've made a simple directive which uses same technique as in J. Bruni's answer.

我做了一个简单的指令,使用了与J. Bruni的回答相同的技巧。

/**
 * Directive which helps to prevent multiple modals opened when clicking same button many times.
 *
 * Just replace "ng-click" with "open-single-modal" in your html. Example:
 *
 * <button open-single-modal="openModal()">Open Window</button>
 *
 * NOTICE! "openModal()" function must return modalInstance which is a result of "$uibModal.open()"
 */
app.directive('openSingleModal', function() {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            var opened = false;

            element.bind('click', function () {
                if(opened) {
                    return;
                }

                opened = true;
                var modalInstance = scope.$eval(attrs.openSingleModal);

                if(!modalInstance || !modalInstance.result || typeof modalInstance.result.then !== 'function') {
                    console.error('Incorrect modal instance returned from the open modal function', element, modalInstance);
                    return;
                }

                modalInstance.result.then(function () {
                    opened = false;
                }, function () {
                    opened = false;
                });
            });
        }
    };
});

To switch your code for this directive just change "ng-click" to "open-single-modal" and the function fired by ng-click must return modal instance.

要切换此指令的代码,只需将“ng-click”更改为“open-single-modal”,ng-click触发的函数必须返回模态实例。

Example. Before:

<a ng-click="openModal()">Open Me!</a>

打开我!

After:

<a open-single-modal="openModal()">Open Me!</a>

打开我!

and

$scope.openModal = function() {
    return $uibModal.open(...);
};

#3


0  

J Bruni's answer is very good, but instead of using an additional variable, use what you already have with modalInstance. Since you declare modal instance higher up, you also gain flexibility to use that variable elsewhere (such as for when you may want to dismiss the dialog).

J Bruni的答案非常好,但不使用额外的变量,而是使用modalInstance已有的内容。由于您将模态实例声明为更高,因此您还可以灵活地在其他地方使用该变量(例如,当您可能想要关闭对话框时)。

    link: function(scope, element, attrs) {
        var modalInstance;        /*assign to undefined if you like to be explicit*/

        element.bind('click', function () {
            if(modalInstance) {
                return;
            }

            modalInstance = scope.$eval(attrs.openSingleModal);

            if(!modalInstance || !modalInstance.result || typeof modalInstance.result.then !== 'function') {
                console.error('Incorrect modal instance returned from the open modal function', element, modalInstance);
                return;
            }

            modalInstance.result.then(function () {
                modalInstance = undefined;
            }, function () {
                modalInstance = undefined;
            });
        });
    }

#1


12  

Use a boolean flag to avoid it:

使用布尔标志来避免它:

var accountSummaryCtrl = function ($scope, $modal, $log) {

    var opened = false;

    $scope.open = function () {

        if (opened) return;

        var modalInstance = $modal.open({
            templateUrl: '/Apps/generic/modal/Templates/AccountSummary.html',
            controller: ModalInstanceCtrl,
            backdrop: false
        });

        opened = true;

        modalInstance.result.then(function (selectedItem) {
            $scope.selected = selectedItem;
            opened = false;
        }, function () {
            $log.info('Modal dismissed at: ' + new Date());
            opened = false;
        });
    };
};

#2


0  

I've made a simple directive which uses same technique as in J. Bruni's answer.

我做了一个简单的指令,使用了与J. Bruni的回答相同的技巧。

/**
 * Directive which helps to prevent multiple modals opened when clicking same button many times.
 *
 * Just replace "ng-click" with "open-single-modal" in your html. Example:
 *
 * <button open-single-modal="openModal()">Open Window</button>
 *
 * NOTICE! "openModal()" function must return modalInstance which is a result of "$uibModal.open()"
 */
app.directive('openSingleModal', function() {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            var opened = false;

            element.bind('click', function () {
                if(opened) {
                    return;
                }

                opened = true;
                var modalInstance = scope.$eval(attrs.openSingleModal);

                if(!modalInstance || !modalInstance.result || typeof modalInstance.result.then !== 'function') {
                    console.error('Incorrect modal instance returned from the open modal function', element, modalInstance);
                    return;
                }

                modalInstance.result.then(function () {
                    opened = false;
                }, function () {
                    opened = false;
                });
            });
        }
    };
});

To switch your code for this directive just change "ng-click" to "open-single-modal" and the function fired by ng-click must return modal instance.

要切换此指令的代码,只需将“ng-click”更改为“open-single-modal”,ng-click触发的函数必须返回模态实例。

Example. Before:

<a ng-click="openModal()">Open Me!</a>

打开我!

After:

<a open-single-modal="openModal()">Open Me!</a>

打开我!

and

$scope.openModal = function() {
    return $uibModal.open(...);
};

#3


0  

J Bruni's answer is very good, but instead of using an additional variable, use what you already have with modalInstance. Since you declare modal instance higher up, you also gain flexibility to use that variable elsewhere (such as for when you may want to dismiss the dialog).

J Bruni的答案非常好,但不使用额外的变量,而是使用modalInstance已有的内容。由于您将模态实例声明为更高,因此您还可以灵活地在其他地方使用该变量(例如,当您可能想要关闭对话框时)。

    link: function(scope, element, attrs) {
        var modalInstance;        /*assign to undefined if you like to be explicit*/

        element.bind('click', function () {
            if(modalInstance) {
                return;
            }

            modalInstance = scope.$eval(attrs.openSingleModal);

            if(!modalInstance || !modalInstance.result || typeof modalInstance.result.then !== 'function') {
                console.error('Incorrect modal instance returned from the open modal function', element, modalInstance);
                return;
            }

            modalInstance.result.then(function () {
                modalInstance = undefined;
            }, function () {
                modalInstance = undefined;
            });
        });
    }