AngularJS ui-router ui-sref, вызывающий ошибку "Uncaught TypeError: Невозможно прочитать свойство" 0 "с неопределенным значением"

У меня есть компонент angularJS, использующий ui-router с двумя простыми состояниями маршрута.

export default function Routes($stateProvider, $urlRouterProvider, $locationProvider) {
    $stateProvider
        .state('details', {
          url: '/',
          template: '<div>...</div>'
        })
        .state('pdf', {
          url: '/viewpdf',
          template: '<pdf-viewer></pdf-viewer>'
        });

    $urlRouterProvider.otherwise(function ($injector, $location) {
        var $state = $injector.get("$state");
        $state.go("details");
    });
}

в details посмотреть у меня есть контроллер, который выбирает документ PDF, а затем изменяет состояние маршрута в обратном вызове с помощью $state.go('pdf');

В представлении PDF у меня есть ui-sref ссылка, возвращающаяся к подробному виду:

<a ui-sref="details">Back to Details</a>

Периодически, когда я нажимаю кнопку Back to Details, он выдает ошибку из page.js и не изменяет состояние маршрута.

Uncaught TypeError: Cannot read property '0' of undefined
    at new Context (page.js:208)
    at Function.page.replace (page.js:154)
    at onpopstate (page.js:347)
    at B (history.min.js:21)
    at history.min.js:22
Context @ page.js:208
page.replace @ page.js:154
onpopstate @ page.js:347
B @ history.min.js:21
(anonymous) @ history.min.js:22

Поиск источника ошибки, который я получаю: (page.js: 208)

/**
   * Initialize a new "request" `Context`
   * with the given `path` and optional initial `state`.
   *
   * @param {String} path
   * @param {Object} state
   * @api public
   */

function Context(path, state) {
    /* ERROR STACK ENDS ON THIS LINE */
    if ('/' == path[0] && 0 != path.indexOf(base)) path = base + path;
    /* END */
    var i = path.indexOf('?');

    this.canonicalPath = path;
    this.path = path.replace(base, '') || '/';

    this.title = document.title;
    this.state = state || {};
    this.state.path = path;
    this.querystring = ~i ? path.slice(i + 1) : '';
    this.pathname = ~i ? path.slice(0, i) : path;
    this.params = [];

    // fragment
    this.hash = '';
    if (!~this.path.indexOf('#')) return;
    var parts = this.path.split('#');
    this.path = parts[0];
    this.hash = parts[1] || '';
    this.querystring = this.querystring.split('#')[0];
  }

URL и вид остаются в /viewpdf, Если я подожду пару секунд и снова нажму кнопку "Назад", все будет работать правильно.

Что вызывает это поведение, и как я могу это исправить?

Изменить Я должен уточнить, когда я ссылаюсь на кнопку назад, я имею в виду кнопку Назад к деталям в /viewpdf просмотр, а не кнопка возврата браузера. Кнопка возврата в браузере не отображает ошибку.

1 ответ

Это может заставить его работать:

$state.go('state',{},{
    reload: true
});

reload Docs:

https://ui-router.github.io/ng1/docs/latest/interfaces/transition.transitionoptions.html

Вы также можете добавить .then() проверить, если ваш pdf состояние все еще загружается при изменении обратно на details государство:

$state.go(..
    .then(
        onfulfilled,
        onrejected
    );

then() Docs:

https://ui-router.github.io/ng1/docs/latest/interfaces/state.transitionpromise.html

Обновить:

Если в компоненте состояния размещены другие навигационные кнопки, этот раздел документов может оказаться полезным.

https://github.com/angular-ui/ui-router/wiki

$rootScope.$on('$viewContentLoaded',
  function(event, viewConfig){
      // Access to all the view config properties.
      // and one special property 'targetView'
      // viewConfig.targetView
  });

В этом слушателе вы можете сделать что-то вроде $scope.loaded = true с ng-disabled для навигационных кнопок.

Этот тестовый код настраивает директиву для элемента управления nav вместе с отключением его до загрузки DOM представления:

angular.module('app',['ui.router'])
  .component('componentHome', {
    template: '<div>Home Page Contents...</div>',
    controller: ['$scope','$state','$rootScope',function($scope,$state,$rootScope){
      $scope.loaded = false;
      $rootScope.$on('$viewContentLoaded',
      function(event, viewConfig){
          $scope.loaded = true;
      });
    }]
  })
  .component('componentA', {
    template: '<div><go></go></div>',
    controller: ['$scope','$state','$rootScope',function($scope,$state,$rootScope){
      $scope.loaded = false;
      $rootScope.$on('$viewContentLoaded',
      function(event, viewConfig){
          $scope.loaded = true;
      });
      $scope.stateName = 'b';
      $scope.stateLabel = 'B';
    }]
  })
  .component('componentB', {
    template: '<div><go></go></div>',
    controller: ['$scope','$state','$rootScope',function($scope,$state,$rootScope){
      $scope.loaded = false;
      $rootScope.$on('$viewContentLoaded',
      function(event, viewConfig){
          $scope.loaded = true;
      });
      $scope.stateName = 'a';
      $scope.stateLabel = 'A';
    }]
  })
  .directive('go',['$state',function($state){
    return {
      restrict: 'E',
      template: '<button ng-disabled="!loaded" state="stateName">Go to Page {{ stateLabel }}</button>',
      link: function(scope,element){
        element.on('click',function(e){
          $state.go(scope.stateName,{},{
            reload: true
          }).then(
            function(){
              // fulfilled
            },
            function(){
              // rejected
            }
          );
        });
      }
    };
  }])
  .config(function($stateProvider){
    $stateProvider.state('/',{ url: '/', component: 'componentHome' });
    $stateProvider.state('a',{ url: '/a', component: 'componentA' });
    $stateProvider.state('b',{ url: '/b', component: 'componentB' });
  })
;

используя HTML:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <script src="jquery.js"></script>
    <script src="angular.js"></script>
    <script src="angular-ui-router.min.js"></script>
    <style>
      .active{ border: 1px dashed red; }
    </style>
  </head>
  <body ng-app="app">
      <a ui-sref="/"  ui-sref-active="active">Home Page</a>
      <a ui-sref="a" ui-sref-active="active">Page A</a>
      <a ui-sref="b" ui-sref-active="active">Page B</a>
      <div>
        <ui-view></ui-view>
      </div>
    <script src="app.js"></script>
  </body>
</html>
Другие вопросы по тегам