Angular Модуль загрузочного модуля пользовательского интерфейса не закрывается на задней кнопке
Я использую модуль из расширений UI Boostrap (http://angular-ui.github.io/bootstrap). Модуль фактически служит диалогом загрузки и автоматически закрывается, когда набор данных веб-службы возвращается в мой код Angular. Когда данные на этой странице загружаются автоматически, диалог открывается немедленно.
Все это отлично работает, когда я впервые попадаю на эту страницу или просто обновляю ее. Проблема возникает, когда я перехожу на более глубокую страницу, а затем пытаюсь вернуться к исходной странице (с помощью диалога) с помощью кнопки браузера. Диалог никогда не исчезает, несмотря на то, что все данные возвращены и вызывается вызов модуля().
Я проследил это до обещания открыть диалоговое окно, которое появляется после вызова увольнения, но опять же, только когда страница загружается с помощью кнопки "Назад". Вызов отклонения никогда не закрывает ничего, потому что он еще не добавлен (я подтвердил это в отладчике).
У меня есть вопрос, как я могу справиться с этим? Есть ли твердый способ поймать завершение загрузки страницы через Angular и дважды проверить, что диалог закрыт? Есть ли лучший способ с помощью UI Bootstrap api?
Я знаю, что это довольно необычный случай, но любые мысли об этом были бы замечательными.
Спасибо!
Ответы
Ответ 1
Решение @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();
}
}
Если вы хотите сделать это для всех страниц, определите это в factory, который всегда загружается или просто сегмент кода app.run:
angular.module('app')
.run(['$rootScope', '$uibModalStack', setupUibModal]);
setupUibModal($rootScope, $uibModalStack) {
$rootScope.$on('$locationChangeStart', handleLocationChange);
function handleLocationChange() {
$uibModalStack.dismissAll();
}
}
Ответ 2
Вот простое решение при использовании 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);
}
})
}]);
надеюсь, что это сэкономит много времени для людей, которые ломают голову.
Ответ 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) Наслаждайтесь.
Ответ 4
УЛУЧШЕНИЕ:
Я нашел ответ от HankScorpio лучшим из них. Я хотел бы включить этот фрагмент для тех, кто использует ui-router, и их рекомендации для модах с выражением состояния.
1) Я хотел получить результат. Наконец (...) перейти в родительское состояние;
2) Я хотел контролировать закрытие модального файла из $stateProvider config, а не путем оснащения контроллера и добавления слушателя в $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() (не закрывающую "stateful" ), просто увольнение):
service.close = function() {
if (currentModal) {
currentModal.dismiss().then(function () {
clearModal();
})
}
}
Преимущество этого заключается в том, что функциональность задней кнопки управляется на уровне конфигурации состояния, а не через прослушиватель.