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>