0

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

12

Я использую директиву "draggable" для поддержки перетаскивания изображений. Однако в зависимости от роли пользователя мне нужно отключить перетаскивание изображений для определенных групп пользователей. Я использую следующий код:

<!-- Атрибут draggable используется как ручка для перетаскивания с помощью события jQuery -->           
<li ng-repeat="template in templates" draggable id="{{template._id}}" type="template" class="template-box">            
<!-- Изображения и другие поля являются дочерними элементами тега "li", которые можно перетаскивать. -->                    
</li>

Метод dragSupported находится в области видимости шаблона и возвращает true или false. Я не хочу создавать два больших дублирующих элемента <li> с помощью ng-if для каждого значения, возвращаемого dragSupported(). Другими словами, я не ищу следующий подход для решения этой проблемы:

<!-- Атрибут draggable используется как ручка для перетаскивания с помощью события jQuery -->           
<li ng-if="dragSupported() == true" ng-repeat="template in templates" draggable id="{{template._id}}" type="template" class="template-box">            
<!-- Изображения и другие поля являются дочерними элементами тега "li", которые можно перетаскивать. -->                    
</li>
<!-- Удаляем директиву "draggable", так как у пользователя нет разрешения на перетаскивание файла -->
<li ng-if="dragSupported() != true" ng-repeat="template in templates" id="{{template._id}}" type="template" class="template-box">            
<!-- Изображения и другие поля являются дочерними элементами тега "li", которые можно перетаскивать. -->                    
</li>

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

3 ответ(ов)

0

Спасибо, Jason, за вашу рекомендацию. Я выбрал немного другой подход. Поскольку я не хочу изменять переменную "scope", я использовал "attrs", чтобы проверить, разрешена ли перетаскивание. Вот подход, который я выбрал и который кажется хорошим на данный момент.

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

app.directive('draggable', function () {
    return {
        // A = атрибут, E = элемент, C = класс и M = HTML комментарий
        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 используется как ручка для перетаскивания с использованием события jQuery -->           
    <li ng-repeat="template in templates" draggable allowdrag="{{userHasPrivilege()}}">            
        <!-- Другие части кода тега li -->                   
    </li> 
</ul>

Контроллер содержит реализацию функции userHasPrivilege().

Не уверен, что это правильный подход, но буду рад услышать мнения.

0

Вопрос: Как добавить или удалить атрибут у элемента в AngularJS?

Ответ: Прямым способом добавить или удалить атрибут у элемента в AngularJS нельзя. Однако вы можете создать директиву, которая будет добавлять нужный атрибут к элементу в зависимости от выполнения определенного условия. Я собрал небольшой пример, который иллюстрирует этот подход.

Пример (Demo): http://jsfiddle.net/VQfcP/31/

Директива

myApp.directive('myDirective', function () {
  return {
    restrict: 'A',
    scope: {
        canDrag: '&'
    },
    link: function (scope, el, attrs, controller) {
        /*
$parent.$index выглядит не самым лучшим образом, и это связано с тем, 
что ng-repeat обрабатывается первым, а затем применяется директива к результату 
текущей итерации повторителя. Вы можете улучшить это поведение, если 
включите повторение в директиву, но это может привести к неоправданному 
разделению ответственности. Вам нужно будет найти лучший способ 
обработать это, если вы хотите использовать этот подход.  
        */
        if (scope.canDrag && scope.canDrag({idx: scope.$parent.$index})) {
            angular.element(el).attr("draggable", "draggable");
        }
    }
  };
});

HTML

<ul>
    <!-- здесь тоже используется $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) {
     // Реализуйте логику проверки прав доступа
     // Верните true, чтобы добавить атрибут
   }
}

Таким образом, с помощью пользовательской директивы вы можете динамически добавлять атрибуты к элементам в зависимости от условий. Не забудьте подходить к этому решению с учетом особенностей и архитектуры вашего приложения.

0

Ваш подход выглядит интересным, и использование директив в AngularJS для условного рендеринга шаблонов может быть хорошим решением. Давайте разберемся с вашим примером.

В вашем коде вы используете атрибут paginated, чтобы определить, следует ли использовать пагинированный шаблон или нет. Это вполне разумная идея, особенно если не все ваши ui-grid требуют пагинации. Однако можно улучшить читаемость и сделать код чуть более элегантным.

Вот как вы могли бы улучшить свой код:

  1. Вместо прямого сравнения строк для определения, является ли paginated истинным, можно использовать привязку к логическим значениям. AngularJS автоматически преобразует строку в логическое значение, если вы используете тернарный оператор.

  2. Вы можете добавить необходимые опции непосредственно внутри конструкции управления логикой, а не только в link функции.

Ваш модифицированный код может выглядеть следующим образом:

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 = scope.$eval(attrs.paginated);

        var template = isPaginated ? paginatedTemplate : nonPaginatedTemplate;
        var linkFn = $compile(template);
        var content = linkFn(scope);
        element.append(content);

        // Здесь можно продолжить инициализацию ui-grid
        // ...
    }
}

Теперь код стал чуть более читаемым и вы избегаете возможных ошибок, возникших из-за неправильного использования строки для логического условия.

Если у вас возникнут дополнительные вопросы или нужны уточнения, не стесняйтесь спрашивать!

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь