有没有办法在路由更改时自动关闭 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.js
而dismissAll()
是@ line 4349
我花了一段时间才找到它。
【讨论】:
以上是关于有没有办法在路由更改时自动关闭 Angular UI Bootstrap 模式?的主要内容,如果未能解决你的问题,请参考以下文章