我想使用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
因为它是一个库)?
答案 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,以动态同步值。