我在使用"UI Router Extras"向应用程序的运行时阶段添加新状态时遇到问题。
一段时间以来,我一直在尝试在用户使用"UI路由器附加""插件"UI路由器附加"成功验证后附加并加载新状态
这里引用了我正在使用的FutureState文档的"UI Router Extras"示例,但我觉得我的场景可能与显示的略有不同,或者我完全错过了一些东西。
PLUNKER中的示例代码-单击登录按钮->http://plnkr.co/edit/PQwNQcLNMyPfpke076yy
荷载和工程下方代码:
我成功地从外部文件加载了初始app.config()lazy。就像下面描述的代码:
PUBLIC-使用"UI Router Extras"的外部初始加载路由-"lazylod/states/PUBLIC-states.json"
[
{
"name": "unauth",
"url": "/",
"controller": "LoginCtrl",
"templateUrl": "app/components/core/login/login.html",
"roles": ["public"]
},
{
"name": "otherwise",
"url": "/",
"roles": ["public"]
}
]
初始应用程序加载-从登录开始成功加载公共状态:
'use strict';
var app = angular.module('app', ['ui.router', 'ct.ui.router.extras'])
.config(function ($urlRouterProvider, $stateProvider, $futureStateProvider) {
app.stateProvider = $stateProvider; // MIGHT NEED REFERNCE LATER?
app.futurestateProvider = $futureStateProvider; // MIGHT NEED REFERNCE LATER?
// ASYNC LOAD OF ROUTES AVAILABLE - SOON TO BE BY ROLE
var futureStateResolve = ["$http", function($http) {
return $http.get("lazyload/states/public-states.json").then(function(response) {
angular.forEach(response.data, function(state) {
$stateProvider.state(state);
console.log(state.roles);
})
})
}];
$futureStateProvider.addResolve(futureStateResolve);
console.log($futureStateProvider);
});
下面的代码不起作用
下面是我对不起作用的部分的代码:
PRIVATE-使用"UI Router Extras"的外部初始加载路由-"lazylod/states/public-states.json"
下面的这个json是在用户登录后使用延迟加载和FutureStates添加的。到目前为止运气不佳:(
[
{
"name": "app",
"abstract": true,
"url": "?menu1State",
"templateUrl": "app/components/core/layout/layout.html",
"controller": "LayoutCtrl",
"roles": ["level1"]
},
{
"name": "app.dashboard",
"url": "/app",
"views": {
"feature": {
"templateUrl": "app/components/core/features/features.html",
"controller": "FeatureCtrl"
}
},
"roles": ["level1"]
},
{
"name": "app.associations_beanbags",
"url": "/app/associations/bean-bags?myParam1&myParam2&modalState",
"views": {
"feature": {
"templateUrl": "app/components/core/features/associations/bean-bags.html",
"controller": "BeanbagsCtrl"
}
},
"roles": ["level2"]
}
]
成功身份验证后触发延迟创建状态的登录按钮:
<a id="btn-fblogin" href="" class="btn btn-primary pull-right" ng-click="callNotify(username, password);">Login</a>
当用户单击登录按钮时,它会模拟成功并调用"$scope.callNotify",从而触发下面的代码。最终发生的是一切正常,直到"app.futureestateProvider.futureState(newState)"'以及尝试调用新状态以查看是否已添加'$state.go('app.dashboard')'。所有这些都会导致一个错误,错误状态如下:
控制台错误:
Error: Could not resolve 'app.dashboard' from state 'unauth'
at Object.transitionTo (http://localhost:3000/bower_components/angular-ui-router/release/angular-ui-router.js:2521:17)
at Object.$state.transitionTo (http://localhost:3000/bower_components/ui-router-extras/release/ct-ui-router-extras.js:136:34)
at Object.$state.transitionTo (http://localhost:3000/bower_components/ui-router-extras/release/ct-ui-router-extras.js:874:55)
at Object.$state.transitionTo (http://localhost:3000/bower_components/ui-router-extras/release/ct-ui-router-extras.js:1301:48)
at Object.go (http://localhost:3000/bower_components/angular-ui-router/release/angular-ui-router.js:2454:21)
at http://localhost:3000/app/components/core/auth/auth-service.js:58:13
at http://localhost:3000/bower_components/angular/angular.js:8113:11
at wrappedCallback (http://localhost:3000/bower_components/angular/angular.js:11573:81)
at wrappedCallback (http://localhost:3000/bower_components/angular/angular.js:11573:81)
at http://localhost:3000/bower_components/angular/angular.js:11659:26
因此,在我看来,各州从未在我们预期的时候真正添加,因此导致了一个错误,比如说"对不起,我看不到你要找的路线。"
'use strict';
app.controller('AuthServiceTestCtrl', ['$window','$scope','$http', '$state', function (win, $scope, $http, $state) {
$scope.callNotify = function(username,password, $stateProvider, $futureStateProvider) {
//notify(username, password); // CALL SERVICE AND GET A RETURN VALUE / ACTION
var loadedAgain = $http.get("lazyload/states/private-states.json").success(function(response) {
if(username == "testuser@example.com" && password == "abc123"){
console.log('Valid Credentials. Logging In.');
// NOW THAT USER IS LOGGED IN REGISTER NEW PRIVATE ROUTE / STATES - PREFERABLY FROM THE SECURED SERVER FILE ('private-states.json') ABOVE
var adminModuleFutureStates = [
{
"name": "app",
"abstract": true,
"url": "?menu1State",
"templateUrl": "app/components/core/layout/layout.html",
"controller": "LayoutCtrl",
"roles": ["level1"]
},
{
"name": "app.dashboard",
"url": "/app",
"views": {
"feature": {
"templateUrl": "app/components/core/features/features.html",
"controller": "FeatureCtrl"
}
},
"roles": ["level1"]
},
{
"name": "app.associations_bean-bags",
"url": "/app/associations/bean-bags?myParam1&myParam2&modalState",
"views": {
"feature": {
"templateUrl": "app/components/core/features/associations/bean-bags.html",
"controller": "BeanBagsCtrl"
}
},
"roles": ["level2"]
}
];
angular.forEach(adminModuleFutureStates, function(newState) {
console.log(newState);
app.futurestateProvider.futureState(newState); // WAS SAVED AS A VAR IN APP CONFIG FOR LATER REFERENCE
});
// FINALLY GO TO ONE OF THE NEWLY ADDED PRIVATE STATES WE JUST ADDED WHICH IS A DASHBOARD
$state.go('app.dashboard');
}
});
};
}]);
我很抱歉没有准备好一个工作示例,我现在就在上面,但我想我现在应该发布这个来展示我所拥有的,并可能得到一个讨论或解决方案,在应用程序已经加载了配置等之后,我如何在运行时通过上面列出的控制器将状态加载到ui路由器。
我最终要做的是:
我真的只需要在登录时公开两个安全的公共路由。然后,一旦用户登录了以前的公共路线,我就试图用新的路线添加或装饰现有的路线,现在用户只能访问他们角色提供的路线。安全对我们来说是极其重要的,我认为在登录页面上预先加载每一条可能的路由没有任何好处,让某人在没有登录的情况下知道什么是出api或服务器路由。
我很抱歉漫无边际,但我得出的结论是,我只是做错了,需要一些额外的眼光来理解为什么我不能在加载后添加新的州。
真的非常感谢你!
PLUNKER中的示例代码-单击登录按钮->http://plnkr.co/edit/PQwNQcLNMyPfpke076yy
我决定改为使用$ocLazyLoad服务,但在应用程序加载并在身份验证等之前使用基本公共路由进行初始配置后,仍使用应用程序注入器动态添加路由。
angular.module("app").configInjector.invoke(['$stateProvider', function ($stateProvider) {
然后,在设置了应用程序注入器,用户通过了身份验证,服务器验证了角色之后,定义允许的ui路由器视图/路由/状态的json响应将循环并动态添加到ui路由器状态定义中。这些路由是在json中定义的,但使用$ocLazyLoad延迟加载的任何附带控制器和视图也是如此。
总的来说,我最终做了以下事情:
angular.module("auth")
.factory('AuthRouteLoaderFactory', ['$window', '$rootScope', '$http', '$state', '$cookieStore','$location', '$timeout','AuthSession',
function(win, $rootScope, $http, $state, $cookieStore, $location, $timeout, AuthSession) {
// PRIVATE INTERFACE
function loadPrivateRoutes() {
console.log('AuthRouteLoaderFactory :: LOADING PRIVATE ROUTES');
var loadedPrivateRoutes = $http.get("lazyload/states/private-states.json").success(function (response) {
angular.module("app").configInjector.invoke(['$stateProvider', function ($stateProvider) {
// VERY IMPORTANT - POST LOGIN ROUTE LOADER / INJECTOR;// DYNAMIC AND SERVER DETERMINED JSON ITERATED BASED ON SPECIFIC ROLES PRE-MADE BY SERVER.
angular.forEach(response, function (state) {
if(!state.abstract){
state.views.feature.resolve[state.views.feature.data.controllerAlias] = ['$ocLazyLoad', function($ocLazyLoad){return $ocLazyLoad.load({"name": state.views.feature.data.controllerAlias,"files": state.views.feature.data.controllerFiles})}];
state.views.feature.resolve.isAuthenticated = function(){
// CHECK IF WE ARE A VALID SESSION FOR EACH LAZY LOAD
//AuthSession.validateToken();
};
}
console.log('AuthRouteLoaderFactory :: loadPrivateroutes state loaded -> ' + state.name);
$stateProvider.state(state.name, state);
});
$state.go('app.dashboard');
}]);
});
}
// FOR NOW WE LOAD ROUTES ANYWAY UNTIL WE CALL API'S /ME OR PING SERVICE, THEN ON SUCCESS WE LOAD ROUTES
if(AuthSession.validateToken()){
$rootScope.hideLoader = true;
loadPrivateRoutes();
console.log('AuthRouteLoaderFactory :: SESSION VALIDATION SUCCESSFUL :: PROCEED');
}
// PUBLIC INTERFACE
return {
testFactory: function() {
console.log('AuthRouteLoaderFactory :: testFactory');
},
isSessionValid: function(){
return $cookieStore.get('fakeLoginSession');
},
invalidateSession: function(){
$cookieStore.remove('fakeLoginSession');
$location.path('/login.html');
},
loadRoutes: loadPrivateRoutes
};
}
]);
公共状态/路线:
[
{
"name": "unauth",
"url": "/",
"controller": "LoginCtrl",
"templateUrl": "app/components/core/login/unauth.html",
"data": {
"roles": ["public"]
}
},
{
"name": "login",
"url": "/login",
"controller": "LoginCtrl",
"templateUrl": "app/components/core/login/unauth.html",
"data": {
"roles": ["public"]
}
},
{
"name": "otherwise",
"url": "/",
"data": {
"roles": ["public"]
}
}
]
私人国家/路线:
[
{ "name": "app", "abstract": true, "url": "", "templateUrl": "app/components/core/layout/layout.html", "controller": "LayoutCtrl" },
{
"name": "app.dashboard",
"views": {
"feature": {
"templateUrl": "lazyload/components/core/features/dashboard/dashboard.html",
"controller": "DashboardCtrl as dashboard",
"resolve": {},
"data": {
"controllerAlias": "dashboard",
"controllerFiles": ["lazyload/components/core/features/dashboard/dashboard-controller.js"]
}
}
}
},
{
"name": "app.associations_role-type",
"views": {
"feature": {
"templateUrl": "lazyload/components/core/features/associations/role-type.html",
"controller": "RoleTypeCtrl as roleType",
"resolve": {},
"data": {
"controllerAlias": "roleType",
"controllerFiles": ["lazyload/components/core/features/associations/role-type-controller.js"]
}
}
}
}
]