UI Router: сохранить URL после $ stateChangeError (при разрешении зависимостей)

0

Szenario:

1) Мы находимся в состоянии А
2) Пользователи нажимают ссылку (цель - состояние B)
3) $ stateChangeStart
4) зависимости состояния B разрешаются, один вызывает ошибку
5) $ stateChangeError
6) url все еще имеет состояние A

Требуемое поведение:

  • Я хочу открыть модальный диалог, содержащий сообщение об ошибке
  • Url должен быть URL состояния B (поэтому пользователь может отправить нам ссылку или нажать обновление, чтобы повторить попытку)
  • В идеале, вид государства A все еще находится на фоне модального
  • Возвращение в историю браузера должно вернуть нас в состояние A (модальный может прослушивать событие popstate и закрывать себя)
  • закрытие модальности также должно вернуть нас в состояние A (так измените URL снова)

В общем, чтобы изменить 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-адрес не будет установлен.

Кто-нибудь имеет Идею, как это достичь? Заранее спасибо :)

Теги:
angular-ui-router
error-handling

1 ответ

1
Лучший ответ

Я нашел способ, который работает в нашем случае:

$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);
          });
   }
});

Ещё вопросы

Сообщество Overcoder
Наверх
Меню