【问题标题】:Is there a way to automatically close Angular UI Bootstrap modal when route changes?有没有办法在路由更改时自动关闭 Angular UI Bootstrap 模式?
【发布时间】:2014-07-08 20:44:15
【问题描述】:

我在模态框内的模板中有链接。当我单击它们时,当前页面会更改,但覆盖和模式会保留。我可以将ng-click="dimiss()" 添加到模式中所有模板的每个链接中,但是有更好的方法吗?例如。是在路线更改成功时自动关闭它,还是在每个模板中只添加一个ng-click 来处理所有链接?

【问题讨论】:

    标签: angularjs angular-ui angular-ui-bootstrap


    【解决方案1】:

    我实际上并没有使用 Angular UI Bootstrap,但是从查看 docs 来看,$modalInstance 对象上似乎有一个 close() 方法。

    因此,以docs 为例,应该可以:

    var ModalInstanceCtrl = function ($scope, $modalInstance, items) {
        $scope.items = items;
        $scope.selected = {
            item: $scope.items[0]
        };
        $scope.ok = function () {
            $modalInstance.close($scope.selected.item);
        };
        $scope.cancel = function () {
            $modalInstance.dismiss('cancel');
        };
    
        // this will listen for route changes and call the callback
        $scope.$on('$routeChangeStart', function(){
            $modalInstance.close();
        });
    };
    

    希望对您有所帮助。

    【讨论】:

      【解决方案2】:

      如果您希望在成功更改路线时关闭所有打开的模式,您可以通过监听$routeChangeSuccess 事件在一个中心位置执行此操作,例如在应用程序的运行块中:

      var myApp = angular.module('app', []).run(function($rootScope, $uibModalStack) {
        $uibModalStack.dismissAll();
      }); 
      

      在这里您可以看到$uibModalStack 服务被注入,您可以在该服务上调用dismissAll 方法 - 此调用将关闭所有当前打开的模式。

      所以,是的,您可以使用一行代码在一处集中处理模态关闭:-)

      【讨论】:

      • 它几乎可以正常工作:) 我有“登录”模式,带有指向“服务条款”页面的链接。打开此模式的按钮位于始终可见的标题栏中,因此也可以在“服务条款”页面上打开此模式。当我在“服务条款”页面上单击此链接时,路线不会改变,也不会触发成功事件。知道如何解决吗?在这种情况下是否会触发任何我可以听的事件?
      • app.run(function ($rootScope, $modalStack) { $rootScope.$on('$routeChangeSuccess', function (newVal, oldVal) { if (oldVal !== newVal) { $modalStack .dismissAll(); } }); });
      • Unknown provider: $uibModalStackProvider
      • 你知道 Angular 2 中的解决方案吗?
      • 您有指向uibModalStack 文档的链接吗?到处都找不到……
      【解决方案3】:

      我通过这样做解决了这个问题:

      $rootScope.$on('$stateChangeSuccess',
      function(event, toState, toParams, fromState, fromParams){
      $modalStack.dismissAll();
      });
      

      【讨论】:

        【解决方案4】:

        更好的方法是查看每当弹出(模态)打开时,在浏览器后退按钮单击(或键盘后退)时,我们停止 URL 更改并关闭弹出窗口。这有助于在我的项目中获得更好的用户体验。

        浏览器返回按钮在没有打开Modal的情况下正常工作。

        使用:

        $uibModalStack.dismiss(openedModal.key);
        

        或

        $uibModalStack.dismissAll;
        

        示例代码:

        .run(['$rootScope', '$uibModalStack',
            function ($rootScope,  $uibModalStack) {       
                // close the opened modal on location change.
                $rootScope.$on('$locationChangeStart', function ($event) {
                    var openedModal = $uibModalStack.getTop();
                    if (openedModal) {
                        if (!!$event.preventDefault) {
                            $event.preventDefault();
                        }
                        if (!!$event.stopPropagation) {
                            $event.stopPropagation();
                        }
                        $uibModalStack.dismiss(openedModal.key);
                    }
                });
            }]);
        

        【讨论】:

        • 我使用了这段代码,但是这与uirouter冲突。当我有一个带有初始化状态更改按钮的模型时,模式关闭,状态更改,但 URL 没有更改为状态的 URL。这是因为上面的代码。我仍在寻找解决方案。如果我有,我会在这里发布。
        【解决方案5】:

        我将这个逻辑保存在模态控制器中。您可以收听$locationChangeStart 事件并在那里关闭模式。之后移除监听器也很好,特别是如果你在$rootScope注册了监听器:

        angular.module('MainApp').controller('ModalCtrl',['$scope','$uibModalInstance',
        function ($scope, $uibModalInstance) {
        
          var dismissModalListener = $scope.$on('$locationChangeStart', function () {
            $uibModalInstance.close();
          });
        
          $scope.$on('$destroy', function() {
            dismissModalListener();
          });
        
        }]);
        

        【讨论】:

          【解决方案6】:

          在事件$stateChangeSuccess 和 然后使用这样的类全局关闭打开的引导模式:

          $rootScope.$on('$stateChangeSuccess',
          function(event, toState, toParams, fromState, fromParams){
          //hide any open bootstrap modals
            angular.element('.inmodal').hide();
          });
          

          如果您想隐藏任何其他模态,例如角度材质对话框 ($mdDialog) 和甜蜜警报对话框,请使用 angular.element('.modal-dialog').hide(); 和 angular.element('.sweet-alert').hide();

          【讨论】:

            【解决方案7】:

            添加这个替代答案。

            根据您的项目,使用$uibModalStack.dismissAll() 可能会触发错误消息。

            正如JB Nizet 在this 答案中所解释的,这是由dismissAll() 拒绝承诺引起的,导致“失败”回调,而不是由close() 触发的“成功”回调。

            上述承诺拒绝可能会触发一个可能不需要的错误处理过程。

            鉴于$uibModalStack 中没有closeAll(),我使用了这个:

                var modal = $uibModalStack.getTop();
                while (modal && this.close(modal.key)) {
                  modal = this.getTop();
                }
            

            这与$uibModalStack.dismissAll() 的行为相同,但使用.close() 而不是.dismiss()。

            我找不到任何描述$uibModalStack 的公共方法的文档,因此,如果有人有兴趣使用/查看$uibModalStack 上可用的其他方法。

            它可能位于\node-modules\angular-ui-boostrap\dist\ui-boostrap-tpls.js 而dismissAll() 是@ line 4349

            我花了一段时间才找到它。

            【讨论】:

              猜你喜欢
              • 2021-06-25
              • 2019-10-28
              • 2021-03-18
              • 1970-01-01
              • 2014-11-03
              • 1970-01-01
              • 2014-07-27
              • 2012-12-18
              • 2013-07-15
              相关资源
              最近更新 更多