2

我正在使用 ng-include 来包含一个持久菜单,该菜单存在于我的 SPA 的所有视图中。

问题是我想为每个用户类型(管理员、访客、用户等)在此菜单中显示不同的选项和内容,这需要首先解决服务功能 authService.loadCurrentUser。

为了轻松舒适地管理此内容,我创建了一个简单的指令,它采用具有所需访问级别的属性,并且在元素的编译阶段,如果给定用户的权限不足,则删除元素和它的孩子。

因此,在尝试使 ng-include 通过 routeProvider 函数失败后,我尝试使用 ng-init,但似乎没有任何效果,用户角色在我注销时仍未定义。

我正在考虑尝试一种新方法,并使整个菜单成为一个指令,其中包含适合每种用户类型的模板,但首先我想尝试解决这个问题。

指示:

'use strict';
/* Directives */
angular.module('myApp.directives', []).
directive('restrict', function(authService){
    return{
        restrict: 'A',
        prioriry: 100000,
        scope: {
            // : '@'
        },
        link: function(){
            // alert('ergo sum!');
        },
        compile:  function(element, attr, linker){
            var user = authService.getUser();
                if(user.role != attr.access){
                console.log(attr.access);
                console.log(user.role);//Always returns undefined!
                    element.children().remove();
                    element.remove();           
                }

        }
    }
});

服务:

'use strict';
/* Services */
angular.module('myApp.services', []).
factory('authService', function ($http, $q) {
    var authServ = {};
    var that = this;
    that.currentUser = {};
    authServ.authUser = function () {
        return $http.head('/users/me', {
            withCredentials: true
        });
    },
    authServ.getUser = function () {
        return that.currentUser;
    },
    authServ.setCompany = function (companyId) {
        that.currentUser.company = companyId;
    },
    authServ.loadCurrentUser = function () {
        var defer = $q.defer();
        $http.get('/users/me', {
            withCredentials: true
        }).
        success(function (data, status, headers, config) {
            console.log(data);
            that.currentUser.company = {};
            that.currentUser.company.id = that.currentUser.company.id ? that.currentUser.company.id : data.main_company;            
            that.currentUser.companies = [];
            for (var i in data.roles) {
                that.currentUser.companies[data.roles[i]['company']] = data.roles[i]['company_name'];
                if (data.roles[i]['company'] == that.currentUser.company.id){
                    that.currentUser.role = data.roles[i]['role_type']; 
                    that.currentUser.company.name = data.roles[i]['company_name'];
                    // console.log(that.currentUser.role);
                } 
            }
            // defer.resolve(data);
            defer.resolve();
        }).
        error(function (data, status, headers, config) {
            that.currentUser.role = 'guest';
            that.currentUser.company = 1;
            defer.reject("reject");
        });  
    return defer.promise;
    }

    return authServ;
});

菜单控制器:

angular.module('myApp.controllers', []).
controller('menuCtrl', function($scope, $route, $location, authService){
    //TODO: Check if this assignment should be local to each $scope func in order to be compliant with 2-way data binding
    $scope.user = authService.getUser();
    console.log($scope.user);
    // $scope.companies = $scope.user.companies;
    $scope.companyOpts = function(){
        // var user = authService.getUser();
        if(typeof $scope.user.company == 'undefined')
            return;

            var companies = [];
            companies[$scope.user.company.id] = $scope.user.company.name;
            for(var i in $scope.user.companies){
                if(i != $scope.user.company.id){
                    companies[i] = $scope.user.companies[i];    
                }
            }
            // console.log(companies);
            // if(nonCurrentComapnies.length > 0){
                console.log(companies);
                return companies;
            // }
    }



    $scope.$watch('user.company.name', function(company){
        for(var i in $scope.user.companies)
            if(company == $scope.user.companies[i].id)
                authService.setCompany(i);
    });
    $scope.$watch(function(){return authService.getUser().company; }, function(company){
        //Refresh the page on company change here, first time, and each time the user changes the select
        // $scope.companyOpts();
        // $scope.currentComapany = company;
    })
;})

主 SPA HTML 页面:

<div ng-init="authservice.loadCurrentUser" ng-include src="'partials/menu.html'"></div>

只有管​​理员才能看到的菜单元素:

<ul class="left" restrict access="admin">
  <li>You are the admin!</li>
</ul>

提前感谢您的任何帮助!

4

2 回答 2

1

我个人会做“反向”的方式。这意味着:当用户角色为“admin”或“user”等时,我将添加菜单......

这样,您可以在“restrict”指令中执行类似的操作:

    ...
    var roleListener = $scope.$watch('user.role', function (newVal, oldVal) {
        if (newVal == $scope.access) {
            // add the menu items
            // supposed that loadcurrentuser be called only once
            // we should clear the watch
            roleListener();
        } else {
            // personally, I would remove the item here too
            // so the menu would be added or removed when user.role update
        }
    });
    ...

还有一件事,仅基于用户角色显示菜单,您可以使用ngSwitch,如下所示:

    <ul class="left" ng-switch="user.role">
        <li ng-switch-when="admin">You are the admin!</li>
        <li ng-switch-when="user">You are the user!</li>
        <li ng-switch-default><img src="some-thing-running.gif"/>Your menu is loading, please wait...</li>
    </ul>

让神奇的 AngularJS 绑定为您呈现菜单!

于 2013-08-22T09:51:55.110 回答
0

对 authServ.getUser 的调用也应该通过内部调用返回一个承诺

authServ.loadCurrentUser

应该对其进行一些修改以检查用户上下文是否存在,以避免进行另一个 API 调用并始终返回用户上下文的解析:

defer.resolve(that.currentUser);

加载用户上下文也应该尽早完成,因为这会启用应用程序的授权。app.run 函数可用于此目的。

希望它可以帮助别人。

于 2016-08-02T23:01:28.430 回答