我正在使用UI Boostrap扩展模块(http://angular-ui.github.io/bootstrap)。该模块实际上用作加载对话框,并在将一组Web服务数据返回到我的Angular代码时自动关闭。当自动加载此页面上的数据时,会立即显示对话框。
当我第一次点击有问题的页面或者只是刷新它时,这一切都很有效。当我进入更深的页面,然后尝试通过浏览器的后退按钮导航回原始页面(使用对话框)时,会出现问题。尽管返回了所有数据并且已经进行了模块的dismiss()调用,但对话框永远不会消失。
我已经将此跟踪到打开对话框的承诺似乎在解雇调用之后发生,但是,仅当通过后退按钮加载页面时。解雇调用永远不会关闭任何东西,因为它尚未添加(我已在调试器中确认了这一点)。
我的问题是如何处理?是否有一种可靠的方法来捕获通过Angular完成页面加载并仔细检查对话框是否已关闭?有没有更好的方法通过UI Bootstrap的api?
我知道这是一个非常不寻常的案例,但对此的任何想法都会很棒。
谢谢!
答案 0 :(得分:6)
@ HankScorpio的解决方案很好,但我认为现在可能有一个简化的选项。
如果您注册$locationChangeStart
或$routeChangeStart
已注册$uibModalStack
并且调用$uibModalStack.dismissAll()
,则无需再存储当前模式。 $locationChangeStart
具有为ngRoute和uiRoute工作的好处。
即。如果只针对一个页面,那么在您的控制器中,您将拥有:
angular.module('app')
.controller('ctrl', ['$scope', '$uibModalStack', ctrl]);
function ctrl($scope, $uibModalStack) {
$scope.$on('$locationChangeStart', handleLocationChange);
function handleLocationChange() {
$uibModalStack.dismissAll();
}
}
如果要对所有页面执行此操作,请在始终加载的工厂或app.run代码段中定义此项:
angular.module('app')
.run(['$rootScope', '$uibModalStack', setupUibModal]);
setupUibModal($rootScope, $uibModalStack) {
$rootScope.$on('$locationChangeStart', handleLocationChange);
function handleLocationChange() {
$uibModalStack.dismissAll();
}
}
答案 1 :(得分:5)
使用ui-router进行状态更改时,这是一个简单的解决方案
关闭后退按钮上的模态弹出窗口,单击angularjs
App.run(['$rootScope', '$modalStack', function ($rootScope, $modalStack) {
$rootScope.$on('$stateChangeStart', function (event) {
var top = $modalStack.getTop();
if (top) {
$modalStack.dismiss(top.key);
}
})
}]);
希望这会为那些打破头脑的人节省大量时间
答案 2 :(得分:3)
我遇到了同样的问题。以下是我修复它的方法。
1)创建一个服务来抽象模态的打开和关闭,并跟踪哪一个是打开的(步骤2必需)。不要直接致电$modal.open()
,而是致电ModalService.open()
。
你走了,你可以找到我写的那个:
(function () {
'use strict';
var theModule = angular.module('services.modalService', ['ui.bootstrap']);
theModule.factory('ModalService', function ($modal) {
var service = {};
var currentModal;
var clearModal = function () {
currentModal = undefined;
};
service.getCurrentModal = function () {
return currentModal;
};
service.open = function (options) {
currentModal = $modal.open(options);
currentModal.result['finally'](clearModal);
return currentModal;
};
return service;
});
}());
2)在控制器中,向$routeChangeStart
添加一个事件监听器,只要有人按下后退按钮,该事件就会触发。
$scope.$on('$routeChangeStart', function(){
var currentModal = ModalService.getCurrentModal();
if(angular.isDefined(currentModal)){
currentModal.dismiss('cancel');
}
});
3)当用户回击时,你的模态现在应该关闭。
4)享受。
答案 3 :(得分:0)
改进:
我发现HankScorpio的答案是最好的。我想为使用ui-router的用户及其对stateful modals的建议添加此代码段。
1)我希望result.finally(...)跳转到父状态;
2)我想控制从$ stateProvider配置关闭模态,而不是通过绑定控制器并向$ routeChangeStart添加一个监听器
以下是打开(并关闭)它的模态的状态示例:
.state('product.detail', {
url: '/detail/{productId}',
onEnter: /*open-modal logic*/,
onExit: ['ModalService', function (ModalService) { ModalService.close()} ]
})
我让ModalService知道$ state,这样关闭模态的结果可以跳转到父视图:
一个。将一个isStateful标志添加到modalService.open(...):
service.open = function (options, isStateful) {
currentModal = $uibModal.open(options);
currentModal.result.finally(function () {
clearModal(isStateful);
});
return currentModal;
};
这样clearModal将返回上一个状态:
var clearModal = function (isStateful) {
currentModal = undefined;
if (isStateful)
$state.go('^');
};
最后,添加上面调用的closeModal()函数(不是“有状态”关闭,只是解雇):
service.close = function() {
if (currentModal) {
currentModal.dismiss().then(function () {
clearModal();
})
}
}
这样做的好处是后退按钮功能是在状态配置级别控制的,而不是通过监听器控制的。