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

时间:2013-09-14 04:57:23

标签: javascript angularjs angularjs-directive

我使用“draggable”指令来支持图像拖动。但是,根据用户的角色,我需要禁用某些用户组的图像拖动。我使用了以下代码。

<!--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。我不想为<li>返回的每个值使用ng-if创建两个大的重复dragSupported()元素。换句话说,我不是在寻找以下方法来解决这个问题。

<!--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>

是否有其他方法可以避免代码欺骗?

4 个答案:

答案 0 :(得分:55)

ng-attr-<attrName>

Angular包含对有条件声明HTML属性的支持,作为动态标题的ng-attr-<attrName>指令。

Official Docs for ng-attr

实施例

在您的情况下,代码可能如下所示:

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

演示

JSFiddle

这包含以下值的使用示例:truefalseundefinednull10""。请注意,通常假值可能会产生意外结果。

答案 1 :(得分:4)

感谢Jason的建议。我这里采取了一些不同的方法。由于我不想更改“范围”变量,因此我使用“attrs”来检查是否允许拖动。以下是到目前为止似乎很好的方法I工具。

指令代码:

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>

Controller正在实现userHasPrivilege()。

不确定这是否正确。寻找想法。

答案 2 :(得分:3)

无法直接在元素中添加或删除属性。但是,您可以创建一个指令,只需在满足条件时将该属性添加到元素中。我把一些东西放在一起说明了这种方法。

演示: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
   }
}

答案 3 :(得分:0)

我使用了不同的方法,因为前面的例子对我不起作用。也许它与使用自定义指令有关?也许有人可以清除它。

在我的特定示例中,我使用的是ui-grid,但并非所有的ui-grid都应该使用分页。我传入一个“paginated”属性然后$基于true / false编译指令。看起来相当野蛮,但希望它可以推动人们朝着积极的方向发展。

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
        // ...

    }
}