有没有办法在路由更改时自动关闭 Angular UI Bootstrap 模式?

Posted

技术标签:

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

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

【问题讨论】:

【参考方案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.jsdismissAll() 是@ line 4349

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

【讨论】:

以上是关于有没有办法在路由更改时自动关闭 Angular UI Bootstrap 模式?的主要内容,如果未能解决你的问题,请参考以下文章

关于angular跳转路由之后不能自动回到顶部的解决方法

Angular-Kendo 在更改时自动完成所选值

如何在Angular项目里监听页面关闭、跳转事件?

如何在Angular 2中每次路由更改时观察路由更改和布尔变量的更改值?

Angular2在路由不活动时添加类

Angular2路由-路由更改时保持组件状态[重复]