Javascript 在单个元素上具有新/隔离作用域的两个属性指令

Javascript 在单个元素上具有新/隔离作用域的两个属性指令,javascript,angularjs,angularjs-directive,angularjs-scope,Javascript,Angularjs,Angularjs Directive,Angularjs Scope,我想使用AngularJS指令在整个应用程序中禁用表单的特定部分,具体取决于用户是否具有特定角色(作为属性值给出;每个元素可能不同)。该指令的代码如下所示: /** @ngInject */ function PermissionDirective() { var directive = { restrict: 'A', scope: true, bindToController: true, controller: con

我想使用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">

只要
就可以了,因此permission
是元素中具有新范围的唯一指令。然而,一些元素也使用了一个模态,这似乎也需要一个新的/隔离的作用域。这会导致角度误差


我的问题是:你如何解决这个问题?如何重新编写
so permission
指令以摆脱内部作用域并使其保持工作状态(因为它是一个库,所以我不能触摸
confirm
对象)

在angular js中,我们最多可以在单个元素上有一个单独的指令。我建议试着装饰一下你的指示。查看本文了解更多详细信息

您应该使用$parse服务与scope进行通信: /


您还可以使用scope.$watch在动态中同步值。

您打算为表单元素授予哪些不同的权限?也许退一步,从一个更简单的HTML角度来看它是可能的

不创建指令,只需使用ng attr readonly和函数分配readonly属性,以确定它是否应该存在。该函数可能存在于窗体的控制器中

<input type="text" ng-attr-readonly="getPermissions()" />
这种方法适合您的情况吗

更新:将此功能放入工厂并重新使用

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

  factory = {
    getPermissions: getPermissions
  }
  return factory;

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

}
然后,在控制器中(假设已注入):

最后,在HTML中,确保将控制器传递到函数中,因为函数不再是控制器的一部分,需要控制器的作用域来检查权限:

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


谢谢你的回答。你能解释一下它是如何解决我的问题的吗?我的问题是1)摆脱多重指令。。。错误,2)仍然能够对具有不同角色的多个元素使用该指令?我的示例可以在没有自己的范围的情况下读取和编辑范围。它不会抛出范围错误true。但如果我理解正确的话,当我这样做的时候,这个指令的一次出现将产生一个状态,该状态将被下一次的出现所覆盖。我不知道,这与你的问题有什么关系。这完全取决于您的代码组织。您可以使用像my dir=“vm.var1”和my dir=“vm.var2”这样的指令,它们会将数据写入不同的变量。是的,放弃指令而使用控制器函数可能对我有用。不过我有一个疑问。此功能必须在整个应用程序中使用,该应用程序由ui路由器中的几个状态层组成。我希望避免在每个控制器中重复该函数。你有解决办法吗?当然!让它成为一个工厂,并在任何需要的地方注入该工厂。然后,您可以在一个地方更改函数本身,它将传播到整个应用程序的所有用途。我已经更新了答案。谢谢。但这是我撞到另一面墙的时候。用户拥有的权限来自web服务。该调用产生的承诺在ui路由器的
resolve
中解析。但是,当我们从控制器分离函数时,我们不能再使用
resolve
。好吧,没有任何合理的方法可以强迫你做出承诺。这里只有
promise.then(){…}
习惯用法,这在这里是无用的,因为我们需要立即得到函数值…根据代码,您可以简单地
返回true
,而不必在
resolve
块中返回承诺。如果您从web服务获得权限,只需向PermissionsFactory添加一个参数,而不是向控制器添加一个参数,在控制器中传递web服务的结果。因为我看不到你写的所有内容,我不知道这是否对你有效。我接受这个答案,因为它让我找到了最满意的解决方案。谢谢你的帮助!
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
<input type="text" ng-attr-readonly="getPermissions(permission)" />