Подтвердить что ты не робот

AngularJS - Использовать директиву атрибута условно

Я использую директиву "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 находится в области шаблона и возвращает true или false. Я не хочу создавать два больших дублирующих элемента <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>

Есть ли другой подход, чтобы избежать двукратности кода?

4b9b3361

Ответ 1

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>

Demo

JSFiddle

Здесь приведены примеры использования для следующих значений: true, false, undefined, null, 1, 0 и "". Обратите внимание, как типично-ложные значения могут давать неожиданные результаты.

Ответ 2

Невозможно напрямую добавить или удалить атрибут из элемента. Однако вы можете создать директиву, которая просто добавляет атрибут к элементу при выполнении условия. Я собрал что-то вместе, что иллюстрирует подход.

Демо: 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 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

Спасибо Джейсону за ваше предложение. Здесь я принял совсем другой подход. Поскольку я не хочу изменять переменную "scope", поэтому я использовал "attrs", чтобы проверить, разрешено ли drag или нет. Следующий подход я инструмент, который кажется хорошим до сих пор.

Код директивы:

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

Не уверен, что это правильно или нет. Ищет мысли.

Ответ 4

Я использовал другой подход, поскольку предыдущие примеры не работали для меня. Возможно, это связано с использованием пользовательских директив? Возможно, кто-то может это очистить.

В моем конкретном примере я использую ui-grid, но не все ui-сетки должны использовать разбиение на страницы. Я передаю атрибут "с разбивкой на страницы", а затем компилирует директиву на основе 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
        // ...

    }
}