根据用户角色加载模板和控制器
虽然从技术上讲,ui-router
的templateUrl函数不支持注入服务,但是您可以使用templateProvider
来注入包含role
变量或异步加载它的service
,然后使用$templateFactory
返回HTML内容。请考虑以下示例:
var app = angular.module('app', ['ui.router']);
app.service('session', function($timeout, $q){
this.role = null;
this.loadRole = function(){
};
});
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
选项来注入
service
,该
service
已经通过templateProvider
解析了role
。请看以下
ui-router
状态定义中
controllerProvider
选项的示例:
controllerProvider: function(session){
if(session.role == 'admin'){
return 'AdminCtrl';
} else {
return 'UserCtrl';
}
}
当然,您可以轻松地从此代码中删除重复项,并定义更易于访问的微型DSL,以使为特定角色和视图定义不同规则更加容易。
以下演示应该帮助您理解代码。
这是正确的方法吗?
通常情况下,这取决于上下文。为了帮助您得出答案,让我首先提出以下问题:
您是否只要隐藏几个按钮和其他操作元素,基本上使页面对普通用户只读,对超级用户可编辑?如果变化很小,我可能会选择使用相同的视图,仅隐藏特定元素,可能伪造类似于ng-if
的指令,允许声明性地启用/禁用特定功能only-role='operator, admin'
。另一方面,如果视图将大不相同,则采用不同的模板可以极大地简化标记。
在不同的角色中,表面上看起来相似的操作内部工作方式是否不同?例如,如果您的编辑操作对于用户
和管理员
角色都可用,但在某种情况下它会启动向导式UI,在另一种情况下则会启动一个复杂的面向高级用户的表单,则有一个单独的控制器
更有意义。另一方面,如果管理员
操作是用户
操作的超集,则使用单个控制器更容易跟进。请注意,在这两种情况下,保留控制器
事项很划算 - 它们应该只将视图粘合到封装在服务/视图模型/模型/选取名称中的行为中
- 您是否会从应用程序的不同位置有许多上下文分离的链接引导到特定的页面?
例如,只需编写
ui-sref="dashboard"
,即可为特定的
页面提供导航,而不考虑当前用户
role
,如果在各种情境下都有用处,则将它们定义在单个路由/状态下似乎更易于维护,而不是使用条件逻辑来构建基于角色的不同
ui-sref
/
ng-href
。但是,您还可以根据用户角色动态地定义路由/状态-动态加载或不加载。
- 不同角色在特定页面上可用的视图和操作是否分别演变,还是一起演变?
有时我们首先为常规用户构建功能,然后为高级用户和最终用户构建功能。如果可以轻松划分明确的边界,将user
和admin
页面的工作分配给团队成员并不罕见。在这种情况下,拥有单独的views
和controllers
可以简化开发人员的工作,避免冲突。当然,这并非全是美好的事物-团队必须非常有纪律性地消除最可能发生的重复。
希望我的建议能帮助您做出决策。