AngularJS,ui.router,基于用户角色加载模板和控制器 [英] AngularJS, ui.router, load template and controller based on user role
问题描述
我开发了一个使用REST API的单页应用程序。用户需要登录才能访问应用程序。当用户登录时,他们被重定向到/ dashboard。在此网址/路线上,我想根据用户的角色(例如正常用户或管理员用户)加载不同的模板和控制器。
我看过 https://github.com/angular-ui / ui-router / wiki ,但没有任何选项支持我想要达到的目标。
- 使用templateUrl和function(stateParams)我无法注入服务,帮助我确定用户角色,以便我可以加载模板,例如视图/ 用户 /dashboard.html或视图/ 管理 /dashboard.html
- 使用templateProvider帮助我确定用户角色,但是如何加载模板?
任何解决方案还应该根据用户角色,例如UserDashboardController或AdminDashboardController。
因此,我需要的是一个单一的路由加载不同的模板和控制器基于用户角色变量
我沿着正确的线路思考,还是应该实施另一个解决方案?
加载基于模板和控制器的on user role
虽然技术上 ui-router
templateUrl函数不支持注入服务,您可以使用 templateProvider
注入包含角色
变量或加载它的服务
$ templateFactory
可返回HTML内容。请考虑以下示例:
var app = angular.module('app',['ui.router']);
app.service('session',function($ timeout,$ q){
this.role = null;
this.loadRole = function {
// load role using axax request and return promise
};
});
app.config(function($ stateProvider,$ urlRouterProvider){
$ stateProvider.state('dashboard',{
url:'/ dashboard',
templateProvider:function(session,$ stateParams,$ templateFactory){
return session.loadRole()。then(function(role){
if(session.role =='admin'){
return $ templateFactory.fromUrl('/ admin / dashboard.html',$ stateParams);
} else {
return $ templateFactory.fromUrl('/ user / dashboard.html',$ stateParams);
}
});
}
});
$ urlRouterProvider.otherwise('/ dashboard');
}
至于 controller
您想要使用 ng-controller
在每个模板的根元素中使用特定的控制器。或者类似地,您可以使用 controllerProvider
选项注入服务
,已经具有角色
由 templateProvider
解析。看看下面的示例 controllerProvider
选项在 ui-router
状态定义:
controllerProvider:function(session){
if(session.role =='admin'){
return'AdminCtrl';
} else {
return'UserCtrl';
}
}
当然,您可以轻松地从此代码中删除重复的定义更容易访问的微DSL,以便为特定角色和视图定义不同的规则。
这是正确的方法吗?
通常这大大取决于上下文。为了帮助您提供答案,我首先建议以下问题:
- 提交给角色的夫妇不同?
您要仅隐藏按钮
s和其他操作元素基本上使一个页面只读的普通用户和可编辑的超级用户?如果更改将很小,我可能会使用相同的视图,只隐藏特定的元素,可能伪造一个类似于 ng-if
的指令,允许启用/禁用特定功能声明性地 only-role ='operator,admin'
。另一方面,如果视图会有很大的不同,那么使用不同的模板可以大大简化标记。
- 在特定页面上有多少 根据角色而有所不同。
在表面上看起来相似的动作在不同角色的内部工作方面不同?例如,如果您为 例如,只要写下用户
和 admin
角色提供编辑如果它开始向导像UI和高级用户的其他复杂形式,那么有一个单独的控制器
更有意义。另一方面,如果 admin
动作是 user
动作的超集,那么拥有单个控制器似乎更容易遵循。请注意,在这两种情况下,保持控制器
的事情是有利的 - 他们应该只粘贴视图封装在服务/视图模型/模型/选择一个名称< 不同的地方的应用程序?
ui即可提供导航到特定 -sref =dashboard
,无论当前用户 role
如果存在于各种上下文中可能是有益的。如果是这种情况,那么在单个路由/状态下定义它们似乎更可维护,那么用于构建不同 ui-sref
/ ng-href
基于角色。
有时我们首先为常规的用户然后为溢价,然后为最终。在团队成员之间划分用户
和 admin
的页面上的工作并不罕见,特别是如果可以轻松绘制清晰的边界。在这种情况下,单独的视图
和 controllers
可以简单地避免冲突。当然,并非所有的彩虹和独角兽 - 团队必须非常纪律,以消除重复,很可能会发生。
希望我的建议帮助你决定。
I have developed a Single Page App that uses a REST api. Users are required to login to access the application. When a user logs in they are redirected to /dashboard. On this URL / route, I would like to load a different template and controller based on the role of the user (e.g. normal user or admin user).
I have looked at https://github.com/angular-ui/ui-router/wiki under the templates section but none of the options support what I am trying to achieve.
- By using templateUrl and function (stateParams) I am not able to inject the service that helps me to determine the user role so that I can load the template, e.g. views/user/dashboard.html or views/admin/dashboard.html
- By using templateProvider I am to inject the service that helps me to determine the user role, but how do I then load the template?
Any solution should also load different controllers based on the user role, for example UserDashboardController or AdminDashboardController.
So essentialy what I need is a single route that loads a different template AND controller based on a user role variable that is set in a service when a user logs in.
Am I thinking along the right lines, or should I be implementing another solution?
Any help on this would be greatly appreciated.
Loading template and controller based on user role
While technically ui-router
templateUrl function does not support injecting services you can use templateProvider
to inject service
that holds role
variable or loads it asynchronously and then use $templateFactory
to return HTML content. Consider following example:
var app = angular.module('app', ['ui.router']);
app.service('session', function($timeout, $q){
this.role = null;
this.loadRole = function(){
//load role using axax request and return promise
};
});
app.config(function($stateProvider, $urlRouterProvider){
$stateProvider.state('dashboard', {
url: '/dashboard',
templateProvider: function(session, $stateParams, $templateFactory){
return session.loadRole().then(function(role){
if(session.role == 'admin'){
return $templateFactory.fromUrl('/admin/dashboard.html', $stateParams);
} else {
return $templateFactory.fromUrl('/user/dashboard.html', $stateParams);
}
});
}
});
$urlRouterProvider.otherwise('/dashboard');
});
As for controller
you can either state that you would like to use specific controller inside root element of each template with ng-controller
. Or similarly you can use controllerProvider
option to inject service
that will already have role
resolved by templateProvider
. Take a look at following example of controllerProvider
option inside ui-router
state definition:
controllerProvider: function(session){
if(session.role == 'admin'){
return 'AdminCtrl';
} else {
return 'UserCtrl';
}
}
Of course you can remove duplicates from this code easily and define a more accessible micro DSL to make defining different rules for particular roles and views easier.
The following demo should help you understand the code.
Is this a right approach?
As usually this greatly depends on context. To help you come up with an answer let me suggest following questions first:
- How much views presented to roles differ?
Are you going to hide only couple of button
s and other action elements basically making a page read only for regular users and editable for superusers? If the changes will be small I would probably go with using the same views and only hiding particular elements, probably forging a directive similar to ng-if
that would allow enabling/disabling particular functionality declaratively only-role='operator, admin'
. On the other hand if views are going to be vastly different then employing different templates can simplify markup greatly.
- How much actions available on particular page differ depending on role?
Do actions that look similar on surface differ in inner workings for different roles? In example if you have Edit action available both for user
and admin
role but in one case it starts wizard like UI and in other a complex form for advanced users then having a separate controller
makes more sense. On the other hand if admin
actions are a superset of user
actions then having single controller seems easier to follow. Note that in both cases keeping controller
things pays off - they should only glue views to behaviour that is encapsulated in services/view models/models/pick a name
- Will you have many contextually separate links leading to particular page from different places of the app?
For instance being able to provide navigation to particular page by simply writing ui-sref="dashboard"
regardless of the current user role
may be beneficial if it exists in various contexts. If that's the case then having them defined under single route/state seems more maintainable then a conditional logic used to build different ui-sref
/ng-href
based on role. However you could also define routes/states dynamically based on user role - loaded dynamically or not
- Will views and actions available to different roles on particular page evolve separately or together?
Sometimes we first build features for regular users then for premium and then for ultimate. It's not unusual to divide work on pages for user
and admin
between team members especially if clear boundaries can be drawn easily. In such case having separate views
and controllers
can simply developers work avoiding conflicts. Of course it's not all rainbows and unicorns - team must be very disciplined to remove duplication that most likely will happen.
Hope that my suggestions will help you decide.
这篇关于AngularJS,ui.router,基于用户角色加载模板和控制器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!