Включить / отключить привязку с помощью AngularJS
Как включить / отключить привязные tags с помощью директивного подхода?
Пример:
- при нажатии на ссылку редактирования, создание и удаление необходимо отключить или вычеркнуть
- при нажатии на ссылку создания, редактировать и удалять нужно отключить или вычеркнуть
JAVASCRIPT:
- Как разрешить ввод только числа (цифры и десятичная точка) на входе?
- Как установить фокус на поле ввода?
- Понимание опции transclude определения директивы?
- В чем разница между ng-app и data-ng-app?
- Каков наилучший способ условного применения атрибутов в AngularJS?
angular.module('ngApp', []).controller('ngCtrl',['$scope', function($scope){ $scope.create = function(){ console.log("inside create"); }; $scope.edit = function(){ console.log("inside edit"); }; $scope.delete = function(){ console.log("inside delete"); }; }]).directive('a', function() { return { restrict: 'E', link: function(scope, elem, attrs) { if(attrs.ngClick || attrs.href === '' || attrs.href === '#'){ elem.on('click', function(e){ e.preventDefault(); if(attrs.ngClick){ scope.$eval(attrs.ngClick); } }); } } }; });
LINK to CODE
- Угловые директивы - когда и как использовать компиляцию, controller, предварительную ссылку и пост-ссылку
- Недопустимое использование директивы ngTransclude в шаблоне
- Угловой ng-стиль с условным выражением
- $ apply vs $ digest при тестировании директивы
- AngularJS - Директивы против controllerов
- Как установить динамический controller для директив?
- Пользовательская форма проверки валидации для сравнения двух полей
- Предварительный просмотр изображения перед загрузкой Angularjs
Обновление: отключение href лучше работает в возврате функции ссылки. Код ниже обновлен.
aDisabled
естественно выполняется до ngClick
потому что директивы сортируются в алфавитном порядке. Когда aDisabled
переименовывается в tagDisabled
, директива не работает.
Чтобы «отключить» тег «a», мне нужны следующие вещи:
- Ссылки
href
не должны выполняться при нажатии - События
ngClick
не срабатывают при нажатии - стили изменены, добавив
disabled
class
Эта директива делает это, подражая директиве ngDisabled. Основываясь на значении директивы a-disabled
, все вышеперечисленные функции переключаются.
myApp.directive('aDisabled', function() { return { compile: function(tElement, tAttrs, transclude) { //Disable ngClick tAttrs["ngClick"] = "!("+tAttrs["aDisabled"]+") && ("+tAttrs["ngClick"]+")"; //return a link function return function (scope, iElement, iAttrs) { //Toggle "disabled" to class when aDisabled becomes true scope.$watch(iAttrs["aDisabled"], function(newValue) { if (newValue !== undefined) { iElement.toggleClass("disabled", newValue); } }); //Disable href on click iElement.on("click", function(e) { if (scope.$eval(iAttrs["aDisabled"])) { e.preventDefault(); } }); }; } }; });
Вот стиль CSS, который может указывать на отключенный тег:
a.disabled { color: #AAAAAA; cursor: default; pointer-events: none; text-decoration: none; }
И вот код в действии, с вашим примером
Моя проблема была несколько иной: у меня есть привязанные tags, которые определяют href
, и я хочу использовать ng-disabled
чтобы предотвратить перемещение ссылки нигде при нажатии. Решение состоит в том, чтобы отключить href
когда ссылка отключена, например:
Foo
В этом случае ng-disabled
используется только для стилизации элемента.
Если вы хотите избежать использования неофициальных атрибутов , вам нужно будет стилизовать его самостоятельно:
Foo
Для людей, которым не нужен сложный ответ, я использовал Ng-If, чтобы решить это для чего-то подобного:
I'm An Anchor I'm just text
Изменение ответа @ Nitin на работу с динамическим отключением:
angular.module('myApp').directive('a', function() { return { restrict: 'E', link: function(scope, elem, attrs) { elem.on('click', function(e) { if (attrs.disabled) { e.preventDefault(); // prevent link click } }); } }; });
Это проверяет наличие отключенного атрибута и его значение при каждом нажатии.
Отказ от ответственности:
ОП сделал этот комментарий по другому вопросу:
Мы можем иметь ngDisabled для кнопок или тегов ввода; используя CSS, мы можем заставить кнопку выглядеть как тег привязки, но это мало помогает! Я больше интересовался тем, как это можно сделать с помощью директивного подхода или углового способа его выполнения?
Вы можете использовать переменную внутри области вашего controllerа, чтобы отключить ссылки / кнопки в соответствии с последней кнопкой / ссылкой, на которую вы нажали, с помощью ng-click
чтобы установить переменную с правильным значением и ng-disabled
чтобы отключить если необходимо, в соответствии со значением переменной.
Я обновил ваш Plunker, чтобы дать вам представление.
Но в основном, это что-то вроде этого:
Вы пытались использовать ленивую оценку выражений вроде disabled || someAction()
disabled || someAction()
?
Предположим, я определил что-то вроде этого в моем controllerе:
$scope.disabled = true;
Затем я могу отключить ссылку и применить встроенные стили:
Higher Level
Или еще лучше отключить ссылку и применить class следующим образом:
Higher Level
Обратите внимание: что этот оператор будет иметь class="disabled"
примененный к элементу DOM.
На этом этапе вам просто нужно обработать то, что вы будете делать GoTo()
. В моем случае это так же просто, как redirect на связанное состояние:
$scope.GoTo = function (state) { if (state != undefined && state.length > 0) { $window.location.hash = state; } };
Вместо ограничения на ngDisabled
вы ограничены тем, что вы решите сделать.
С помощью этой техники я успешно применил проверку уровня разрешений для включения или отключения доступа пользователя к определенной части моего модуля.
Простой плункер, чтобы продемонстрировать суть
Вы можете создать настраиваемую директиву, которая каким-то образом похожа на ng-disabled и отключить определенный набор элементов:
- наблюдая изменения свойств пользовательской директивы, например,
my-disabled
. - клонировать текущий элемент без добавления обработчиков событий.
- добавьте свойства css к клонированному элементу и другим атрибутам или обработчикам событий, которые предоставят отключенное состояние элемента.
- когда изменения обнаружены в наблюдаемом свойстве, замените текущий элемент клонированным элементом.
HTML
CREATE
EDIT
DELETE
RESET
JAVASCRIPT
directive('myDisabled', function() { return { link: function(scope, elem, attr) { var color = elem.css('color'), textDecoration = elem.css('text-decoration'), cursor = elem.css('cursor'), // double negation for non-boolean attributes eg undefined currentValue = !!scope.$eval(attr.myDisabled), current = elem[0], next = elem[0].cloneNode(true); var nextElem = angular.element(next); nextElem.on('click', function(e) { e.preventDefault(); e.stopPropagation(); }); nextElem.css('color', 'gray'); nextElem.css('text-decoration', 'line-through'); nextElem.css('cursor', 'not-allowed'); nextElem.attr('tabindex', -1); scope.$watch(attr.myDisabled, function(value) { // double negation for non-boolean attributes eg undefined value = !!value; if(currentValue != value) { currentValue = value; current.parentNode.replaceChild(next, current); var temp = current; current = next; next = temp; } }) } } });
Сделайте тумблер в соответствующей области, чтобы опустить ссылку .
Во-первых, создайте следующие CSS-classы в вашем файле .css.
.disabled { pointer-events: none; cursor: default; } .enabled { pointer-events: visible; cursor: auto; }
Добавьте переменную $ scope.state и $ scope.toggle. Измените свой controller в JS-файле, например:
$scope.state='on'; $scope.toggle='enabled'; $scope.changeState = function () { $scope.state = $scope.state === 'on' ? 'off' : 'on'; $scope.toggleEdit(); }; $scope.toggleEdit = function () { if ($scope.state === 'on') $scope.toggle = 'enabled'; else $scope.toggle = 'disabled'; };
Теперь в HTML tags редактируются как:
CREATE
EDIT
DELETE
Чтобы избежать проблемы с отключением ссылки, измените class DOM CSS в конце функции.
document.getElementById("create").className = "enabled";
Вы можете переопределить тег a
с помощью угловой директивы:
angular.module('myApp').directive('a', function() { return { restrict: 'E', link: function(scope, elem, attrs) { if ('disabled' in attrs) { elem.on('click', function(e) { e.preventDefault(); // prevent link click }); } } }; });
В html:
Next
Я ожидаю, что привязывающие tags приведут к статической странице с URL-адресом. Я думаю, что кнопки больше подходят для вашего прецедента, а затем вы можете использовать ngDisabled для его отключения. Из документов: https://docs.angularjs.org/api/ng/directive/ngDisabled