AngularJS - Условное использование атрибутного директивы
Я использую директиву "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 ответ(ов)
Спасибо, 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().
Не уверен, что это правильный подход, но буду рад услышать мнения.
Вопрос: Как добавить или удалить атрибут у элемента в 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, чтобы добавить атрибут
}
}
Таким образом, с помощью пользовательской директивы вы можете динамически добавлять атрибуты к элементам в зависимости от условий. Не забудьте подходить к этому решению с учетом особенностей и архитектуры вашего приложения.
Ваш подход выглядит интересным, и использование директив в AngularJS для условного рендеринга шаблонов может быть хорошим решением. Давайте разберемся с вашим примером.
В вашем коде вы используете атрибут paginated
, чтобы определить, следует ли использовать пагинированный шаблон или нет. Это вполне разумная идея, особенно если не все ваши ui-grid
требуют пагинации. Однако можно улучшить читаемость и сделать код чуть более элегантным.
Вот как вы могли бы улучшить свой код:
Вместо прямого сравнения строк для определения, является ли
paginated
истинным, можно использовать привязку к логическим значениям. AngularJS автоматически преобразует строку в логическое значение, если вы используете тернарный оператор.Вы можете добавить необходимые опции непосредственно внутри конструкции управления логикой, а не только в
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
// ...
}
}
Теперь код стал чуть более читаемым и вы избегаете возможных ошибок, возникших из-за неправильного использования строки для логического условия.
Если у вас возникнут дополнительные вопросы или нужны уточнения, не стесняйтесь спрашивать!
Должен ли $watch в Angular удаляться при уничтожении scope?
Работа с $scope.$emit и $scope.$on в AngularJS
Как привязать значения списка чекбоксов в AngularJS?
Как установить свойство value в ng-options AngularJS?
AngularJS - UI Router - Программное добавление состояний