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

AngularJS - Use attribute directive conditionally

本文关键字:属性 指令 有条件 AngularJS      更新时间:2023-09-26

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

<!--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 。我不想通过对 dragSupported() 返回的每个值使用 ng-if 来创建两个大的重复<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 中,作为动态标题的 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

这包含以下值的用法示例:truefalseundefinednull10"" 。请注意通常为假的值如何产生意外的结果。

感谢杰森的建议。我在这里采取了不同的方法。由于我不想更改"scope"变量,因此我使用"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'
                });
            }
        }
    }
});

网页代码:

<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()。

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

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

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

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

在我的特定示例中,我使用的是 ui-grid,但并非所有 ui-grid 都应该使用分页。 我传入一个"分页"属性,然后根据真/假$compile指令。 看起来很野蛮,但希望它能把人们推向积极的方向。

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