AngularJS
Пользовательские директивы
Поиск…
Вступление
Здесь вы узнаете о функции Directives от AngularJS. Ниже вы найдете информацию о том, какие директивы, а также основные и расширенные примеры того, как их использовать.
параметры
параметр | подробности |
---|---|
объем | Свойство, чтобы установить область действия директивы. Он может быть установлен как false, true или как область выделения: {@, =, <, &}. |
область действия: ложь | Директива использует родительскую область. Никакой области, созданной для директивы. |
scope: true | Директива наследует родительскую область прототипно как новый охват ребенка. Если существует несколько директив для одного элемента с запросом новой области, то они будут разделять одну новую область. |
объем: { @ } | Односторонняя привязка свойства области действия директивы к значению атрибута DOM. Поскольку значение атрибута, связанное с родителем, оно изменится в области директивы. |
scope: {=} | Двунаправленная привязка атрибута, которая изменяет атрибут родителя, если атрибут директивы изменяется и наоборот. |
scope: {<} | Односторонняя привязка свойства области действия директивы и выражения атрибута DOM. Выражение оценивается в родительском. Это отслеживает идентификатор родительского значения, поэтому изменения в объекте в родительском объекте не будут отражены в директиве. Изменения свойства объекта в директиве будут отражены в родительском, поскольку оба ссылаются на один и тот же объект |
объем: { & } | Позволяет директиве передать данные в выражение, которое будет оцениваться в родительском. |
компиляция: функция | Эта функция используется для выполнения преобразования DOM в шаблоне директивы перед запуском функции связи. Он принимает tElement (шаблон директивы) и tAttr (список атрибутов, объявленных в директиве). Он не имеет доступа к области. Он может возвращать функцию, которая будет зарегистрирована в качестве функции post-link или может вернуть объект с параметрами pre и post будет зарегистрирована как функция pre-link и post-link . |
ссылка: функция / объект | Свойство link можно настроить как функцию или объект. Он может принимать следующие аргументы: scope (область директивы), iElement (элемент DOM, где применяется директива), iAttrs (набор атрибутов элемента DOM), контроллер (массив контроллеров, требуемый директивой), transcludeFn. Он в основном используется для настройки DOM-прослушивателей, просмотра свойств модели для изменений и обновления DOM. Он выполняется после клонирования шаблона. Он настроен независимо, если функция компиляции отсутствует. |
функция предварительной ссылки | Функция связи, которая выполняется до того, как будет создана какая-либо дочерняя ссылка. По умолчанию функции дочерних директивных ссылок выполняются перед функциями родительской директивной ссылки, а функция предварительной привязки позволяет родительскому соединению сначала. Один случай использования - если ребенок требует данных от родителя. |
функция пост-ссылки | Функция ссылок, которую руководители после дочерних элементов связаны с родителем. Он обычно используется для прикрепления обработчиков событий и доступа к дочерним директивам, но данные, требуемые дочерней директивой, не должны устанавливаться здесь, потому что дочерняя директива уже была связана. |
ограничивать: строка | Определяет, как вызвать директиву из DOM. Возможные значения (Предположим, что наше директивное имя - demoDirective ): E - Имя элемента ( <demo-directive></demo-directive> ), A - Атрибут ( <div demo-directive></div> ), C - Соответствующий класс ( <div class="demo-directive"></div> ), M - по комментарию ( <!-- directive: demo-directive --> ). Свойство restrict может также поддерживать несколько параметров, например - restrict: "AC" ограничивает директивой атрибут OR Class . Если опущено, значением по умолчанию является "EA" (элемент или атрибут). |
требуют: 'demoDirective' | Найдите контроллер demoDirective на текущем элементе и введите его контроллер в качестве четвертого аргумента функции связывания. Выбросьте ошибку, если она не найдена. |
require: '? demoDirective' | Попытайтесь найти контроллер demoDirective или передать null в ссылку fn, если он не найден. |
require: '^ demoDirective' | Найдите контроллер demoDirective, выполнив поиск элемента и его родителей. Выбросьте ошибку, если она не найдена. |
require: '^^ demoDirective' | Найдите контроллер demoDirective, выполнив поиск родителей элемента. Выбросьте ошибку, если она не найдена. |
require: '? ^ demoDirective' | Попытайтесь найти контроллер demoDirective, выполнив поиск элемента и его родителей или передав null в ссылку fn, если не найден. |
require: '? ^^ demoDirective' | Попытайтесь найти контроллер demoDirective, выполнив поиск родительского элемента или передайте null в ссылку fn, если не найден. |
Создание и использование пользовательских директив
Директивы - одна из самых мощных функций angularjs. Пользовательские директивы angularjs используются для расширения функциональности html путем создания новых элементов html или пользовательских атрибутов для обеспечения определенного поведения тега html.
directive.js
// Create the App module if you haven't created it yet
var demoApp= angular.module("demoApp", []);
// If you already have the app module created, comment the above line and create a reference of the app module
var demoApp = angular.module("demoApp");
// Create a directive using the below syntax
// Directives are used to extend the capabilities of html element
// You can either create it as an Element/Attribute/class
// We are creating a directive named demoDirective. Notice it is in CamelCase when we are defining the directive just like ngModel
// This directive will be activated as soon as any this element is encountered in html
demoApp.directive('demoDirective', function () {
// This returns a directive definition object
// A directive definition object is a simple JavaScript object used for configuring the directive’s behaviour,template..etc
return {
// restrict: 'AE', signifies that directive is Element/Attribute directive,
// "E" is for element, "A" is for attribute, "C" is for class, and "M" is for comment.
// Attributes are going to be the main ones as far as adding behaviors that get used the most.
// If you don't specify the restrict property it will default to "A"
restrict :'AE',
// The values of scope property decides how the actual scope is created and used inside a directive. These values can be either “false”, “true” or “{}”. This creates an isolate scope for the directive.
// '@' binding is for passing strings. These strings support {{}} expressions for interpolated values.
// '=' binding is for two-way model binding. The model in parent scope is linked to the model in the directive's isolated scope.
// '&' binding is for passing a method into your directive's scope so that it can be called within your directive.
// The method is pre-bound to the directive's parent scope, and supports arguments.
scope: {
name: "@", // Always use small casing here even if it's a mix of 2-3 words
},
// template replaces the complete element with its text.
template: "<div>Hello {{name}}!</div>",
// compile is called during application initialization. AngularJS calls it once when html page is loaded.
compile: function(element, attributes) {
element.css("border", "1px solid #cccccc");
// linkFunction is linked with each element with scope to get the element specific data.
var linkFunction = function($scope, element, attributes) {
element.html("Name: <b>"+$scope.name +"</b>");
element.css("background-color", "#ff00ff");
};
return linkFunction;
}
};
});
Эта директива затем может быть использована в приложении как:
<html>
<head>
<title>Angular JS Directives</title>
</head>
<body>
<script src = "//ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="directive.js"></script>
<div ng-app = "demoApp">
<!-- Notice we are using Spinal Casing here -->
<demo-directive name="World"></demo-directive>
</div>
</body>
</html>
Шаблон объекта определения директивы
demoApp.directive('demoDirective', function () {
var directiveDefinitionObject = {
multiElement:
priority:
terminal:
scope: {},
bindToController: {},
controller:
controllerAs:
require:
restrict:
templateNamespace:
template:
templateUrl:
transclude:
compile:
link: function(){}
};
return directiveDefinitionObject;
});
-
multiElement
- установить значение true, и любые узлы DOM между началом и концом имени директивы будут собраны и сгруппированы вместе в качестве директивных элементов -
priority
- позволяет указать порядок применения директив, когда несколько директив определены на одном элементе DOM. Сначала устанавливаются директивы с более высокими номерами. -
terminal
- установить значение true, а текущий приоритет будет последним набором директив для выполнения -
scope
- задает область действия директивы -
bind to controller
- связывает свойства области напрямую с директивным контроллером - функция конструктора
controller
- контроллера -
require
- требуется другая директива и ввести свой контроллер в качестве четвертого аргумента функции связывания -
controllerAs
- имя ссылается на контроллер в области директивы, чтобы позволить на контроллер ссылаться из шаблона директивы. -
restrict
- ограничить директиву элементом, атрибутом, классом или комментарием -
templateNameSpace
- устанавливает тип документа, используемый шаблоном директивы: html, svg или math. html - значение по умолчанию -
template
- html markup, который по умолчанию заменяет содержимое элемента директивы или обертывает содержимое элемента директивы, если transclude is true -
templateUrl
- url, предоставляемый асинхронно для шаблона -
transclude
- Извлечь содержимое элемента, в котором появляется директива, и сделать его доступным для директивы. Содержимое скомпилировано и предоставлено директиве в качестве функции перехода. -
compile
- функция преобразования шаблона DOM -
link
- используется только в том случае, если свойство компиляции не определено. Функция связи отвечает за регистрацию DOM-прослушивателей, а также за обновление DOM. Он выполняется после клонирования шаблона.
Пример базовой директивы
супермен-directive.js
angular.module('myApp', [])
.directive('superman', function() {
return {
// restricts how the directive can be used
restrict: 'E',
templateUrl: 'superman-template.html',
controller: function() {
this.message = "I'm superman!"
},
controllerAs: 'supermanCtrl',
// Executed after Angular's initialization. Use commonly
// for adding event handlers and DOM manipulation
link: function(scope, element, attributes) {
element.on('click', function() {
alert('I am superman!')
});
}
}
});
сверхчеловека template.html
<h2>{{supermanCtrl.message}}</h2>
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.js"></script>
<script src="superman-directive.js"><script/>
</head>
<body>
<div ng-app="myApp">
<superman></superman>
</div>
</body>
</html>
Вы можете проверить больше о директивах restrict
и link
функциях на официальной документации AngularJS по Директивам
Как создать восстанавливаемый компонент с помощью директивы
Директивы AngularJS - это то, что контролирует рендеринг HTML внутри приложения AngularJS. Они могут быть элементом Html, атрибутом, классом или комментарием. Директивы используются для управления DOM, добавления нового поведения к элементам HTML, привязки данных и многих других. Некоторыми примерами директив, которые являются угловыми, являются ng-model, ng-hide, ng-if.
Аналогичным образом можно создать свою собственную настраиваемую директиву и сделать ее доступной. Для создания Справочника по пользовательским директивам. Смысл создания многоразовых директив заключается в том, чтобы создать набор директив / компонентов, написанных вами, так же, как angularjs предоставляет нам использование angular.js. Эти многоразовые директивы могут быть особенно полезными, когда у вас есть набор приложений / приложений, которые требуют последовательного поведения, внешнего вида и восприятия. Примером такого многоразового компонента может быть простая панель инструментов, которую вы можете использовать в своем приложении или в разных приложениях, но вы хотите, чтобы они вели себя одинаково или выглядели одинаково.
Во-первых, создайте папку с именем resuableComponents в папке приложения и сделайте reusableModuleApp.js
reusableModuleApp.js:
(function(){
var reusableModuleApp = angular.module('resuableModuleApp', ['ngSanitize']);
//Remember whatever dependencies you have in here should be injected in the app module where it is intended to be used or it's scripts should be included in your main app
//We will be injecting ng-sanitize
resubaleModuleApp.directive('toolbar', toolbar)
toolbar.$inject=['$sce'];
function toolbar($sce){
return{
restrict :'AE',
//Defining below isolate scope actually provides window for the directive to take data from app that will be using this.
scope : {
value1: '=',
value2: '=',
},
}
template : '<ul> <li><a ng-click="Add()" href="">{{value1}}</a></li> <li><a ng-click="Edit()" href="#">{{value2}}</a></li> </ul> ',
link : function(scope, element, attrs){
//Handle's Add function
scope.Add = function(){
};
//Handle's Edit function
scope.Edit = function(){
};
}
}
});
mainApp.js:
(function(){
var mainApp = angular.module('mainApp', ['reusableModuleApp']); //Inject resuableModuleApp in your application where you want to use toolbar component
mainApp.controller('mainAppController', function($scope){
$scope.value1 = "Add";
$scope.value2 = "Edit";
});
});
index.html:
<!doctype html>
<html ng-app="mainApp">
<head>
<title> Demo Making a reusable component
<head>
<body ng-controller="mainAppController">
<!-- We are providing data to toolbar directive using mainApp'controller -->
<toolbar value1="value1" value2="value2"></toolbar>
<!-- We need to add the dependent js files on both apps here -->
<script src="js/angular.js"></script>
<script src="js/angular-sanitize.js"></script>
<!-- your mainApp.js should be added afterwards --->
<script src="mainApp.js"></script>
<!-- Add your reusable component js files here -->
<script src="resuableComponents/reusableModuleApp.js"></script>
</body>
</html>
Директива по умолчанию используется для повторного использования компонентов. Когда вы делаете директивы в отдельном угловом модуле, он фактически делает его экспортируемым и многоразовым в разных приложениях с угловыми функциями. Новые директивы можно просто добавить внутри reusableModuleApp.js, а reusableModuleApp может иметь собственный контроллер, службы, объект DDO внутри директивы для определения поведения.
Основная директива с шаблоном и изолированной областью
Создание настраиваемой директивы с изолированной областью отделяет область внутри директивы от внешней области, чтобы наша директива не случайно меняла данные в родительской области и ограничивала ее чтением частных данных из родительской области.
Чтобы создать изолированную область действия и позволить нашей настраиваемой директиве связываться с внешней областью, мы можем использовать опцию scope
которая описывает, как сопоставить привязки внутренней области директивы с внешней областью.
Фактические привязки выполняются с дополнительными атрибутами, прикрепленными к директиве. Связующие параметры определяются с scope
опции и объект с пар ключ-значение:
- Ключ , который соответствует изолированному свойству свойства нашей директивы
- Значение , которое сообщает Angular, как привязать внутреннюю область директивы к атрибуту соответствия
Простой пример директивы с изолированной областью:
var ProgressBar = function() {
return {
scope: { // This is how we define an isolated scope
current: '=', // Create a REQUIRED bidirectional binding by using the 'current' attribute
full: '=?maxValue' // Create an OPTIONAL (Note the '?'): bidirectional binding using 'max-value' attribute to the `full` property in our directive isolated scope
}
template: '<div class="progress-back">' +
' <div class="progress-bar"' +
' ng-style="{width: getProgress()}">' +
' </div>' +
'</div>',
link: function(scope, el, attrs) {
if (scope.full === undefined) {
scope.full = 100;
}
scope.getProgress = function() {
return (scope.current / scope.size * 100) + '%';
}
}
}
}
ProgressBar.$inject = [];
angular.module('app').directive('progressBar', ProgressBar);
Пример использования этой директивы и привязка данных из области действия контроллера к внутренней области директивы:
контроллер:
angular.module('app').controller('myCtrl', function($scope) {
$scope.currentProgressValue = 39;
$scope.maxProgressBarValue = 50;
});
Посмотреть:
<div ng-controller="myCtrl">
<progress-bar current="currentProgressValue"></progress-bar>
<progress-bar current="currentProgressValue" max-value="maxProgressBarValue"></progress-bar>
</div>
Построение многоразового компонента
Директивы могут использоваться для создания повторно используемых компонентов. Ниже приведен пример компонента «ящик пользователя»:
userBox.js
angular.module('simpleDirective', []).directive('userBox', function() {
return {
scope: {
username: '=username',
reputation: '=reputation'
},
templateUrl: '/path/to/app/directives/user-box.html'
};
});
Controller.js
var myApp = angular.module('myApp', ['simpleDirective']);
myApp.controller('Controller', function($scope) {
$scope.user = "John Doe";
$scope.rep = 1250;
$scope.user2 = "Andrew";
$scope.rep2 = 2850;
});
myPage.js
<html lang="en" ng-app="myApp">
<head>
<script src="/path/to/app/angular.min.js"></script>
<script src="/path/to/app/js/controllers/Controller.js"></script>
<script src="/path/to/app/js/directives/userBox.js"></script>
</head>
<body>
<div ng-controller="Controller">
<user-box username="user" reputation="rep"></user-box>
<user-box username="user2" reputation="rep2"></user-box>
</div>
</body>
</html>
пользователя box.html
<div>{{username}}</div>
<div>{{reputation}} reputation</div>
Результатом будет:
John Doe
1250 reputation
Andrew
2850 reputation
Декоратор директивы
Иногда вам могут понадобиться дополнительные функции из директивы. Вместо того, чтобы переписывать (копировать) директиву, вы можете изменить поведение директивы.
Декоратор будет выполнен во время фазы инъекции.
Чтобы сделать это, подайте код .config в свой модуль. Директива называется myDirective, поэтому вам нужно настроить myDirectiveDirective. (это в угловом соглашении [читайте о провайдерах]).
Этот пример изменит templateUrl директивы:
angular.module('myApp').config(function($provide){
$provide.decorator('myDirectiveDirective', function($delegate){
var directive = $delegate[0]; // this is the actual delegated, your directive
directive.templateUrl = 'newTemplate.html'; // you change the directive template
return $delegate;
})
});
Этот пример добавляет событие onClick к элементу директивы при щелчке, это происходит во время фазы компиляции.
angular.module('myApp').config(function ($provide) {
$provide.decorator('myDirectiveTwoDirective', function ($delegate) {
var directive = $delegate[0];
var link = directive.link; // this is directive link phase
directive.compile = function () { // change the compile of that directive
return function (scope, element, attrs) {
link.apply(this, arguments); // apply this at the link phase
element.on('click', function(){ // when add an onclick that log hello when the directive is clicked.
console.log('hello!');
});
};
};
return $delegate;
});
});
Подобный подход может использоваться как для Провайдеров, так и для Услуг.
Наследование и совместимость директив
Угловые js-директивы могут быть вложенными или быть совместимыми.
В этом примере директива Adir предоставляет директиву Bdir - это контроллер $ scope, так как Bdir требует Adir.
angular.module('myApp',[]).directive('Adir', function () {
return {
restrict: 'AE',
controller: ['$scope', function ($scope) {
$scope.logFn = function (val) {
console.log(val);
}
}]
}
})
Удостоверьтесь, что необходимо установить: '^ Adir' (посмотрите на угловую документацию, некоторые версии не требуют символа ^).
.directive('Bdir', function () {
return {
restrict: 'AE',
require: '^Adir', // Bdir require Adir
link: function (scope, elem, attr, Parent) {
// Parent is Adir but can be an array of required directives.
elem.on('click', function ($event) {
Parent.logFn("Hello!"); // will log "Hello! at parent dir scope
scope.$apply(); // apply to parent scope.
});
}
}
}]);
Вы можете вложить свою директиву таким образом:
<div a-dir><span b-dir></span></div>
<a-dir><b-dir></b-dir> </a-dir>
Не требуется, чтобы директивы были вложены в ваш HTML.