Szenario:
1) Мы находимся в состоянии А
2) Пользователи нажимают ссылку (цель - состояние B)
3) $ stateChangeStart
4) зависимости состояния B разрешаются, один вызывает ошибку
5) $ stateChangeError
6) url все еще имеет состояние A
Требуемое поведение:
В общем, чтобы изменить URL-адрес без перезагрузки представления, я бы сделал следующее:
// in .config() block
$urlRouterProvider.deferIntercept();
// somewhere else
var preventNextSuccess = false;
var unbindError = $rootScope.$on('$stateChangeError', function () {
preventNextSuccess = true;
$location.path($state.href(toState, toParams));
unbindError();
});
$rootScope.$on('$locationChangeSuccess', function $event) {
if (preventNextSuccess) {
$event.preventDefault();
preventNextSuccess = false;
} else {
$urlRouter.sync();
}
});
$urlRouter.listen();
Но в этом случае предотвращение события $ locationChangeSuccess не помогает, потому что ошибка появляется после $ locationStateStart и $ stateChangeStart и до $ locationChangeSuccess и $ stateChangeSuccess.
Поэтому с этим решением я получаю бесконечный цикл. Предотвращение события запуска не помогает ни потому, что в этом случае URL-адрес не будет установлен.
Кто-нибудь имеет Идею, как это достичь? Заранее спасибо :)
Я нашел способ, который работает в нашем случае:
$rootScope.$on('$stateChangeError', function ($event, toState, toParams, fromState, fromParams, response) {
ErrorModalService.openErrorModal({error: error});
var failedStateUrl = $state.href(toState, toParams);
var fromStateUrl = $state.href(fromState, fromParams);
if (fromStateUrl !== null && fromStateUrl !== failedStateUrl) {
var unbindLocationChange = $rootScope.$on('$locationChangeStart', function ($event) {
$event.preventDefault();
unbindLocationChange();
});
// After $stateChangeError, the url gets set back to the url of the previous state.
// We want to keep the failedUrl (without reloading that state though)
$timeout(function () {
history.pushState(null, '', failedStateUrl);
});
}
});