Here is what i have so far with ui-router states:
以下是我到目前为止ui-router状态:
$stateProvider
.state('tools', {
url: '/tools/:tool',
template: '<div ui-view=""></div>',
abstract: true,
onEnter: function ($stateParams, $state, TOOL_TYPES) {
if (TOOL_TYPES.indexOf($stateParams.tool) === -1) {
$state.go('error');
}
}
})
.state('tools.list', {
url: '',
templateUrl: 'app/tools/tools.tpl.html',
controller: 'ToolsController'
})
.state('tools.view', {
url: '/:id/view',
templateUrl: 'app/tools/partials/tool.tpl.html',
controller: 'ToolController'
});
As you can see parent state has parameter tool
which can be only in TOOL_TYPES
array. So in case when tool
is not available, i want to redirect to the error page.
正如您所见,父状态具有参数工具,该工具只能在TOOL_TYPES数组中。因此,如果工具不可用,我想重定向到错误页面。
Actually, everything works as expected, but i get two errors:
实际上,一切都按预期工作,但我得到两个错误:
TypeError: Cannot read property '@' of null
TypeError:无法读取null的属性'@'
TypeError: Cannot read property '@tools' of null
TypeError:无法读取null的属性“@tools”
So i guess, child states have been 'hit' anyway. Is it possible to prevent this? Or maybe there is some other way to achieve what i want?
所以我想,无论如何,儿童状态已被“击中”。有可能阻止这种情况吗?或者也许还有其他方法来实现我想要的东西?
1 个解决方案
#1
9
Angular ui-router's documentation mentions that onEnter
callbacks gets called when a state becomes active, hence, the child states were activated.
Angular ui-router的文档提到当状态变为活动状态时调用onEnter回调,因此激活了子状态。
To solve this problem you need to implement two things:
要解决此问题,您需要实现两件事:
-
Create a
resolve
that returns a rejected promise once a specific condition does not apply to that state. Make sure that the rejected promise is passed with information regarding the state to redirect to.创建一个在特定条件不适用于该状态时返回被拒绝的承诺的决心。确保传递被拒绝的承诺,并提供有关要重定向到的状态的信息。
-
Create a
$stateChangeError
event handler in the$rootScope
and use the 6th parameter which is the representation of the information you have passed in the rejected promise. Use the information to create your redirect implementation.在$ rootScope中创建$ stateChangeError事件处理程序,并使用第6个参数,该参数表示您在被拒绝的承诺中传递的信息。使用该信息创建重定向实现。
Javascript
angular.module('app', ['ui.router'])
.value('TOOL_TYPES', [
'tool1', 'tool2', 'tool3'
])
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('error', {
url: '/error',
template: 'Error!'
})
.state('tools', {
url: '/tools/:tool',
abstract: true,
template: '<ui-view></ui-view>',
resolve: {
tool_type: function($state, $q, $stateParams, TOOL_TYPES) {
var index = TOOL_TYPES.indexOf($stateParams.tool);
if(index === -1) {
return $q.reject({
state: 'error'
});
}
return TOOL_TYPES[index];
}
}
})
.state('tools.list', {
url: '',
template: 'List of Tools',
controller: 'ToolsController'
})
.state('tools.view', {
url: '/:id/view',
template: 'Tool View',
controller: 'ToolController'
});
})
.run(function($rootScope, $state) {
$rootScope.$on('$stateChangeError', function(
event, toState, toStateParams,
fromState, fromStateParams, error) {
if(error && error.state) {
$state.go(error.state, error.params, error.options);
}
});
})
.controller('ToolsController', function() {})
.controller('ToolController', function() {});
#1
9
Angular ui-router's documentation mentions that onEnter
callbacks gets called when a state becomes active, hence, the child states were activated.
Angular ui-router的文档提到当状态变为活动状态时调用onEnter回调,因此激活了子状态。
To solve this problem you need to implement two things:
要解决此问题,您需要实现两件事:
-
Create a
resolve
that returns a rejected promise once a specific condition does not apply to that state. Make sure that the rejected promise is passed with information regarding the state to redirect to.创建一个在特定条件不适用于该状态时返回被拒绝的承诺的决心。确保传递被拒绝的承诺,并提供有关要重定向到的状态的信息。
-
Create a
$stateChangeError
event handler in the$rootScope
and use the 6th parameter which is the representation of the information you have passed in the rejected promise. Use the information to create your redirect implementation.在$ rootScope中创建$ stateChangeError事件处理程序,并使用第6个参数,该参数表示您在被拒绝的承诺中传递的信息。使用该信息创建重定向实现。
Javascript
angular.module('app', ['ui.router'])
.value('TOOL_TYPES', [
'tool1', 'tool2', 'tool3'
])
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('error', {
url: '/error',
template: 'Error!'
})
.state('tools', {
url: '/tools/:tool',
abstract: true,
template: '<ui-view></ui-view>',
resolve: {
tool_type: function($state, $q, $stateParams, TOOL_TYPES) {
var index = TOOL_TYPES.indexOf($stateParams.tool);
if(index === -1) {
return $q.reject({
state: 'error'
});
}
return TOOL_TYPES[index];
}
}
})
.state('tools.list', {
url: '',
template: 'List of Tools',
controller: 'ToolsController'
})
.state('tools.view', {
url: '/:id/view',
template: 'Tool View',
controller: 'ToolController'
});
})
.run(function($rootScope, $state) {
$rootScope.$on('$stateChangeError', function(
event, toState, toStateParams,
fromState, fromStateParams, error) {
if(error && error.state) {
$state.go(error.state, error.params, error.options);
}
});
})
.controller('ToolsController', function() {})
.controller('ToolController', function() {});