我正在创建一个具有动态状态的应用,有时我需要从网址中解析状态名称。
例如:我有/dashboard/user/12268
,我需要获得状态'dashboard.user'
。
有没有办法用ui-router
给出的工具做到这一点?我现在无法知道如何做到这一点......
我正在使用requireJS加载动态模块。第一次没有问题,因为用户被发送到登录状态。登录后,我使用require只加载用户有权访问的状态。但是当用户重新加载页面时,我再次加载模块,并需要将URL解析为状态,并且存在问题。我已经开始尝试使用urlMatcherFactory但无法解决它们。
在URL解析后加载状态。
流程是(在刷新页面http://localhost:8090/index.html#/dashboard/user/12268
之后):
ui-router
要在应用程序引导程序之后加载状态,我使用了包含状态和常量的Ben Nadel's solution变体。
RequireJS中的data-main
有这个初始化代码:
require.config({
// REQUIREJS CONFIGURATION
});
require(['app'], function (app) {
app.bootstrap(document);
var ng = angular.injector(['ng']);
var $window = ng.get('$window')
var $q = ng.get('$q');
var appStorage = $window.localStorage;
var loadedManifests;
try {
loadedManifests = JSON.parse(appStorage.getItem('loadedManifests'));
} catch(e) {
loadedManifests = [];
}
if (!angular.isArray(loadedManifests) || loadedManifests.length === 0) {
$q.all([
app.loadManifest('login/manifest'), //loadMainfest function loads the states for login
app.loadManifest('logout/manifest') //load states for logout
])
.then(function () {
app.injector.get('$rootScope').$evalAsync(function () {
app.injector.get('$state').go('login');
});
});
} else {
var promisesArray = [];
for(var i = 0; loadedManifests[i]; i++) {
promisesArray.push(app.loadManifest(loadedManifests[i])); //load all manifests registered on localstorage
}
$q.all(promisesArray).then(function(){
//TODO: Stuck. Get URL from querystring and resolve to valid state, or redirect to /login
});
}
});
loadManifest
函数在我的应用程序(服务,工厂,控制器,路由器......)上注册所有后引导元素。
感谢您的帮助,
ALX
答案 0 :(得分:17)
https://github.com/angular-ui/ui-router/issues/1651
您可以使用.decorator
上的$stateProvider
挂钩公开内部状态实现。你可以装饰国家建设者的任何财产;我随意选择了“父母”。
app.config(function($stateProvider) {
$stateProvider.decorator('parent', function (internalStateObj, parentFn) {
// This fn is called by StateBuilder each time a state is registered
// The first arg is the internal state. Capture it and add an accessor to public state object.
internalStateObj.self.$$state = function() { return internalStateObj; };
// pass through to default .parent() function
return parentFn(internalStateObj);
});
});
现在,您可以使用.$$state()
访问内部状态对象,例如
var publicState = $state.get("foo");
var privateInternalState = publicState.$$state();
其次,遍历$ state.get()中的每个状态,并根据您的URL片段对它们进行测试。
angular.forEach($state.get(), function(state) {
var privatePortion = state.$$state();
var match = privatePortion.url.exec(url, queryParams);
if (match) console.log("Matched state: " + state.name + " and parameters: " + match);
});
答案 1 :(得分:1)
最后,我必须对ui-router的$state
服务进行一些小修改才能找到解决方案。
结果是存储在服务中的状态具有的信息比$state.get()
方法中给出的信息多。所以我迭代它们以获得与我的URL匹配的状态:
/**
* @ngdoc function
* @name ui.router.state.$state#fromUrl
* @methodOf ui.router.state.$state
*
* @description
* A method to resolve a state and its parameters from a given URL
*
* @returns {boolean} Returns a state that matches with the given URL, or undefined if no match
*/
$state.fromUrl = function(url) {
if(!angular.isString(url)) {
//Only valid strings allowed
return undefined;
}
var keys = objectKeys(states);
//Iterate over all states
for(var i = 0; i < keys.length; i++) {
var state = states[keys[i]];
var stateArgs = state.url.exec(url);
//If the state's URL does not match then stateArgs will be false
if(!!stateArgs) {
return {
name: state.name,
args: stateArgs
}
}
}
return undefined;
};
&#13;
的问候,
ALX
答案 2 :(得分:0)
要让@Chris T解决方案为我工作,我在服务中执行此操作:
app.service('Helper', ['$state', '$location',
function($state, $location){
var services = {};
services.stateIs = function(state_name){
var current_path = $location.$$path;
var state = $state.get(state_name);
if(state){
var state_regexp = state.$$state().url.regexp;
return state_regexp.test(current_path);
}else{
return false;
}
}
return services;
}
]);
所以稍后我可以在任何地方注入Helper并执行此操作:
if(Helper.stateIs('app.user')){
//yeah
}
答案 3 :(得分:-2)
当前状态可以从$ state service获得。像$state.current
检查此api http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.$state