在单个元素上具有新/隔离范围的两个属性指令

时间:2016-10-03 12:15:00

标签: javascript angularjs angularjs-directive angularjs-scope

我想使用AngularJS指令根据用户是否具有特定角色(给定为属性值;每个元素可能不同)来禁用整个应用程序中表单的特定部分。该指令的代码如下:

/** @ngInject */
function PermissionDirective() {
    var directive = {
        restrict: 'A',
        scope: true,
        bindToController: true,
        controller: controller,
        controllerAs: 'permission',
        link: link
    };

    function link(scope, element, attrs) {
        scope.soPermission = attrs.soPermission;
    }

    return directive;
}

/** @ngInject */
function controller($scope, $attrs, ...) {
    var permission = this;
    permission.granted = false;
    $scope.soPermission = $attrs.soPermission;
    init();

    function init() {
        var requiredPermission = $scope.soPermission;

        permission.granted = // determine if user can use element
    }
}

请注意,它需要自己的范围才能工作。 HTML中的用法是:

<button type="button" ng-disabled="... || !permission.granted" so-permission="WRITE">

只要so-permission是具有新范围的元素中的唯一指令,一切都很好。但是,某些元素也使用confirm模态,这似乎也需要一个新的/隔离的范围。这会导致Multiple directives...角度误差。

我的问题是:你是如何解决这个问题的?我如何重写so-permission指令以摆脱内部范围并仍然保持工作(因为我无法触及confirm因为它是一个库)?

3 个答案:

答案 0 :(得分:1)

您打算为表单元素提供哪些不同的权限?也许可以退一步从更简单的HTML角度来看待它?

您可以简单地使用ng-attr-readonly将readonly属性与函数一起分配,而不是创建指令,以确定它是否应该存在。该功能可以存在于您的表单控制器中。

<input type="text" ng-attr-readonly="getPermissions()" />

功能:

this.getPermissions = function() {
  if (this.granted === 'READ') return undefined;
  return 'readonly';
}

这种方法适用于您的情况吗?

更新:将此功能转换为工厂并重新使用。

angular.module("myApp").factory("PermissionsFactory",PermissionsFactory);
function PermissionsFactory() {

  factory = {
    getPermissions: getPermissions
  }
  return factory;

  function getPermissions(ctrl) {
    if (ctrl.granted === 'READ') return undefined;
    return 'readonly';
  } 

}

然后,在你的控制器中(假设你注射了它):

this.getPermissions = PermissionsFactory.getPermissions

最后,在你的HTML中,一定要将控制器传递给函数,因为该函数不再是控制器的一部分,需要控制器的范围来检查权限:

<input type="text" ng-attr-readonly="getPermissions(permission)" />

答案 1 :(得分:0)

在角度js中,我们在单个元素上最多只能有一个隔离指令。我建议尝试装饰你的指令。查看此文章了解更多详细信息 Decorating Directives

答案 2 :(得分:0)

你应该使用$ parse服务,与范围沟通:     /

** @ngInject */
        function PermissionDirective() {
        var directive = {
        restrict: 'A',
        link: link
    };

function link(scope, element, attrs) {
    var getter = $parse(attrs.soPermission);
    var setter = getter.setter;
    setter(scope, val); // set value to scope
    var value = getter(scope); //get value from scope
}

return directive;
}

你也可以使用范围。$ watch,以动态同步值。