AngularJS,ui.router,基于用户角色的加载模板和控制器

use*_*298 32 templates controller user-roles angularjs angular-ui-router

我开发了一个使用REST api的单页应用程序.用户需要登录才能访问该应用程序.当用户登录时,他们将被重定向到/ dashboard.在此URL /路由上,我想根据用户的角色(例如普通用户管理员用户)加载不同的模板和控制器.

我查看了模板部分下的https://github.com/angular-ui/ui-router/wiki,但没有一个选项支持我想要实现的目标.

  • 通过使用templateUrl和function(stateParams),我无法注入帮助我确定用户角色的服务,以便我可以加载模板,例如views/user /dashboard.html或views/admin /dashboard.html
  • 通过使用templateProvider,我将注入帮助我确定用户角色的服务,但是如何加载模板呢?

任何解决方案还应根据用户角色加载不同的控制器,例如UserDashboardController或AdminDashboardController.

所以我需要的是根据用户登录时在服务中设置的用户角色变量加载不同模板和控制器的单一路径.

我是在考虑正确的方向,还是应该实施另一种解决方案?

任何有关这方面的帮助将不胜感激.

mie*_*sol 23

根据用户角色加载模板和控制器

虽然技术上ui-routertemplateUrl函数不支持注入服务,但您可以使用templateProvider注入service保存role变量或异步加载它然后用于$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');
});
Run Code Online (Sandbox Code Playgroud)

至于controller你可以声明你想在每个模板的根元素内使用特定的控制器ng-controller.或类似的,你可以使用controllerProvider选项来注入service将已经role被解决了templateProvider.看一下状态定义中的以下controllerProvider选项示例ui-router:

controllerProvider: function(session){
  if(session.role == 'admin'){
    return 'AdminCtrl';
  } else {
    return 'UserCtrl';  
  }
}
Run Code Online (Sandbox Code Playgroud)

当然,您可以轻松地从此代码中删除重复项,并定义更易于访问的微型DSL,以便更轻松地为特定角色和视图定义不同的规则.

以下演示应该可以帮助您理解代码.

这是一种正确的方法吗?

通常这很大程度上取决于背景.为了帮助您找到答案,我先建议您提出以下问题:

  • 提交给角色的观看次数有多大?

你是否只隐藏几个buttons和其他动作元素,基本上只为普通用户设置一个页面,并为超级用户编辑?如果更改很小,我可能会使用相同的视图并且只隐藏特定元素,可能伪造类似的指令ng-if将允许以声明方式启用/禁用特定功能only-role='operator, admin'.另一方面,如果视图将大不相同,那么使用不同的模板可以大大简化标记.

  • 特定页面上可用的操作数量因角色而异?

表面上看起来相似的行为在不同角色的内部工作方面有所不同吗?例如,如果您有和角色一起使用的编辑操作user,admin但在一种情况下,它启动向导,如UI,而在其他复杂的形式,高级用户,然后有一个单独的controller更有意义.另一方面,如果admin动作是动作的超集,user则单个控制器似乎更容易遵循.请注意,在这两种情况下保持controller收益 - 它们应该只将视图粘贴到封装在services/view models/models /中的名称

  • 您是否有许多上下文单独的链接,从应用程序的不同位置导致特定页面

例如,如果存在于各种上下文中,则无论当前用户如何能够通过简单地写入而向特定页面提供导航可能是有益的.如果是这种情况,那么在单个路由/状态下定义它们似乎更易于维护,然后用于构建不同/ 基于角色的条件逻辑.但是,您也可以根据用户角色动态定义路由/状态 - 动态加载或不加载ui-sref="dashboard"roleui-srefng-href

  • 特定页面上不同角色可用的视图和操作是单独演变还是一起演变?

有时我们首先为普通用户构建功能,然后是高级版,然后是最终用户.在团队成员之间useradmin团队成员之间划分工作并不罕见,特别是如果可以轻松绘制清晰的边界.在这种情况下,分开views并且controllers可以简单地开发人员避免冲突.当然,不是所有的彩虹和独角兽 - 团队必须非常自律,以消除最有可能发生的重复.

希望我的建议能帮助你做出决定.


Kha*_* TO 15

我是在考虑正确的方向,还是应该实施另一种解决方案?

IMO,你不应该这样做.

在这里,我根据您的应用程序的实现方式提出了另外两种解决方案.

1)如果可以配置角色的权限(您可以使用单独的页面来配置角色,为角色分配权限,......).然后使用你的角色只有1模板1控制器(普通用户,管理员用户和更多......)和使用ng-show,ng-class..相应地显示你的HTML.

在这种情况下,我们不关心用户是普通用户还是管理员用户,这只是我们角色的名称.我们关心的是权利和它的动态=>因此,我们应该根据配置的权限动态显示html(当然,当用户执行操作以防止用户制造恶意时,也会在服务器端进行检查http请求并发布到服务器).如果我们使用单独的模板,那么无数的情况.

这个解决方案的重点是页面的功能您的角色相同,您只需要根据用户显示/隐藏页面的功能.

2)如果角色的权限是固定的(无法配置),则普通用户和管理员用户的视图功能不同.最好为这些视图使用单独的状态,并根据登录用户授权访问这些视图(当然,用户执行操作时,服务器端也有授权).

原因是:管理员用户视图和普通用户视图具有不同的功能(应该相互分离)


Sha*_* C. 7

如果您使用的角度大于1.2,则可以使用templateUrl作为函数执行指令.

所以基本的想法是你有一个仪表板视图,它有一个自定义指令,它将根据用户级别确定模板.所以像这样:

(function () {
  'use strict';
  angular.module('App.Directives')
    .directive('appDashboard', ['UserManager', function (UserManager) {
      return {
        restrict: 'EA',
        templateUrl: function(ele, attr){
            if (UserManager.currentUser.isAdmin){
                return 'admin.html';
            }else{
                return 'user.html';
            }
        }
      };
    }]);
})(); 
Run Code Online (Sandbox Code Playgroud)