AngularJS – 有条件地使用属性指令

我正在使用“可拖动”指令来支持图像拖动。 但是,根据用户的angular色,我需要禁用某些用户组的图片拖动function。 我使用了下面的代码。

<!--draggable attribute is used as handle to make it draggable using jquery event--> <li ng-repeat="template in templates" draggable id="{{template._id}}" type="template" class="template-box"> <!-- Images and other fields are child of "li" tag which can be dragged.--> </li> 

dragSupported方法在模板范围内,并返回truefalse 。 我不想通过使用ng-ifdragSupported()返回的每个值创build两个大的重复<li>元素。 换句话说,我不是在寻找下面的办法来解决这个问题。

 <!--draggable attribute is used as handle to make it draggable using jquery event--> <li ng-if="dragSupported() ==true" ng-repeat="template in templates" draggable id="{{template._id}}" type="template" class="template-box"> <!-- Images and other fields are child of "li" tag which can be dragged.--> </li> <!--remove "draggable" directive as user doesn't have permission to drag file --> <li ng-if="dragSupported() !=true" ng-repeat="template in templates" id="{{template._id}}" type="template" class="template-box"> <!-- Images and other fields are child of "li" tag which can be dragged.--> </li> 

有没有其他的方法来避免代码重复?

ng-attr-<attrName>

支持有条件地声明一个HTML属性包含在Angular中作为dynamic标题的ng-attr-<attrName>指令。

ng-attr官方文档

在你的情况下,代码可能看起来像这样:

 <li id="{{template._id}}" class="template-box" type="template" ng-repeat="template in templates" ng-attr-draggable="dragSupported() === true" ></li> 

演示

的jsfiddle

这包含用于以下值的示例: truefalseundefinednull0"" 。 请注意,通常falsey值可能会产生意想不到的结果。

没有办法直接添加或删除元素的属性。 但是,您可以创build一个指令,在满足条件时简单地将该属性添加到元素。 我已经把东西放在一起,说明了方法。

演示: http : //jsfiddle.net/VQfcP/31/

指示

 myApp.directive('myDirective', function () { return { restrict: 'A', scope: { canDrag: '&' }, link: function (scope, el, attrs, controller) { /* $parent.$index is ugly, and it's due to the fact that the ng-repeat is being evaluated first, and then the directive is being applied to the result of the current iteration of the repeater. You may be able to clean this by transcluding the repeat into the directive, but that may be an inappropriate separation of concerns. You will need to figure out the best way to handle this, if you want to use this approach. */ if (scope.canDrag&& scope.canDrag({idx: scope.$parent.$index})) { angular.element(el).attr("draggable", "draggable"); } } }; }); 

HTML

 <ul> <!-- same deal with $parent --> <li ng-repeat="x in [1, 2, 3, 4, 5]" my-directive="true" can-drag="checkPermissions(idx)">{{$parent.x}}</li> </ul> 

调节器

 function Ctl($scope) { $scope.checkPermissions = function(idx) { // do whatever you need to check permissions // return true to add the attribute } } 

谢谢你的build议。 我在这里采取了不同的方法。 由于我不想更改“范围”variables,因此我使用“attrs”来检查是否允许拖动。 以下是迄今为止好像好的做法的工具。

指令代码:

 app.directive('draggable', function () { return { // A = attribute, E = Element, C = Class and M = HTML Comment restrict: 'A', replace:true, link: function (scope, element, attrs) { if(attrs.allowdrag =="true") { element.draggable({ cursor: 'move', helper: 'clone', class:'drag-file' }); } } } }); 

HTML代码:

 <ul> <!--draggable attribute is used as handle to make it draggable using jquery event--> <li ng-repeat="template in templates" draggable allowdrag="{{userHasPrivilege()}}" > <!--Ohter code part of li tag--> </li> </ul> 

控制器正在执行userHasPrivilege()。

不知道这是否正确的方式。 寻找想法。

我用了一个不同的方法,因为前面的例子不适合我。 也许它与使用自定义指令有关? 也许有人可以明白这一点。

在我的例子中,我使用的是ui-grid,但并不是所有的ui-grids都应该使用分页。 我传入一个“分页”属性,然后$基于真/假编译指令。 看起来相当残酷但希望它可以推动人们积极的方向。

HTML

 <sync-grid service="demand" paginated="true"></sync-grid> 

指示

 angular .module('app.directives') .directive('syncGrid', ['$compile', SyncGrid]); function SyncGrid($compile){ var nonPaginatedTemplate = '' + '<div>' + ' <div ui-grid="gridOptions" class="grid"></div>' + '</div>'; var paginatedTemplate = '' + '<div>' + ' <div ui-grid="gridOptions" class="grid" ui-grid-pagination></div>' + '</div>'; return { link: link, restrict: 'E', replace: true }; function link(scope, element, attrs) { var isPaginated = attrs['paginated']; var template = isPaginated ? paginatedTemplate : nonPaginatedTemplate; var linkFn = $compile(template); var content = linkFn(scope); element.append(content); // Continue with ui-grid initialization code // ... } }