AngularJS
Direttive personalizzate
Ricerca…
introduzione
Qui apprenderai la funzione Directives di AngularJS. Di seguito troverai informazioni su quali sono le Direttive, oltre a esempi di base e avanzati su come usarle.
Parametri
Parametro | Dettagli |
---|---|
scopo | Proprietà per impostare l'ambito della direttiva. Può essere impostato come falso, vero o come ambito isolato: {@, =, <, &}. |
campo di applicazione: falsy | La direttiva usa l'ambito genitore. Nessun ambito creato per direttiva. |
ambito: vero | La direttiva eredita l'ambito genitore prototipicamente come un nuovo ambito figlio. Se ci sono più direttive sullo stesso elemento che richiede un nuovo ambito, condivideranno un nuovo ambito. |
scopo: { @ } | Associazione unidirezionale di una proprietà dell'ambito direttiva a un valore di attributo DOM. Poiché il valore dell'attributo è associato al genitore, cambierà nell'ambito della direttiva. |
ambito: {=} | Associazione dell'attributo bidirezionale che modifica l'attributo nel genitore se l'attributo direttiva cambia e viceversa. |
ambito: {<} | Associazione unidirezionale di una proprietà dell'ambito direttiva e un'espressione dell'attributo DOM. L'espressione viene valutata nel genitore. Questo controlla l'identità del valore padre in modo che le modifiche a una proprietà dell'oggetto nel padre non vengano riflesse nella direttiva. Le modifiche a una proprietà dell'oggetto in una direttiva si rifletteranno in parent, poiché entrambi fanno riferimento allo stesso oggetto |
scopo: { & } | Consente alla direttiva di passare i dati a un'espressione da valutare nel genitore. |
compilare: funzione | Questa funzione viene utilizzata per eseguire la trasformazione DOM sul modello di direttiva prima dell'esecuzione della funzione di collegamento. Accetta tElement (il modello di direttiva) e tAttr (elenco di attributi dichiarati sulla direttiva). Non ha accesso all'ambito. Può restituire una funzione che verrà registrata come funzione post-link oppure restituire un oggetto con proprietà pre e post con le quali saranno registrate come funzioni pre-link e post-link . |
link: funzione / oggetto | La proprietà del collegamento può essere configurata come funzione o oggetto. Può ricevere i seguenti argomenti: ambito (ambito direttiva), iElement (elemento DOM in cui viene applicata la direttiva), iAttrs (raccolta di attributi dell'elemento DOM), controller (matrice di controller richiesta dalla direttiva), transcludeFn. È utilizzato principalmente per impostare i listener DOM, osservare le proprietà del modello per le modifiche e aggiornare il DOM. Esegue dopo la clonazione del modello. È configurato indipendentemente se non esiste una funzione di compilazione. |
funzione pre-link | Funzione di collegamento che viene eseguita prima delle funzioni di collegamento figlio. Per impostazione predefinita, le funzioni di collegamento della direttiva figlio vengono eseguite prima delle funzioni di collegamento della direttiva padre e la funzione di pre-collegamento consente al genitore di collegarsi per primo. Un caso d'uso è se il bambino richiede dati dal genitore. |
funzione post-link | Funzione di collegamento che i dirigenti dopo gli elementi figlio sono collegati al genitore. Viene comunemente utilizzato per il collegamento di gestori di eventi e l'accesso alle direttive secondarie, ma i dati richiesti dalla direttiva figlio non dovrebbero essere impostati qui perché la direttiva figlio sarà già stata collegata. |
limitare: stringa | Definisce come chiamare la direttiva dall'interno del DOM. Possibili valori (supponendo che il nome della nostra direttiva sia demoDirective ): E - Nome dell'elemento ( <demo-directive></demo-directive> ), A - Attributo ( <div demo-directive></div> ), C - Corrispondenza ( <div class="demo-directive"></div> ), M - Per commento ( <!-- directive: demo-directive --> ). La proprietà restrict può anche supportare più opzioni, ad esempio - restrict: "AC" limiterà la direttiva a Attribute OR Class . Se omesso, il valore predefinito è "EA" (Elemento o Attributo). |
richiede: 'demoDirective' | Individuare il controller di demoDirective sull'elemento corrente e iniettarne il controller come quarto argomento della funzione di collegamento. Fai un errore se non lo trovi. |
richiede: "? demoDirective" | Tentare di individuare il controller di demoDirective o passare null al collegamento fn se non trovato. |
richiede: '^ demoDirective' | Individua il controller di demoDirective cercando l'elemento e i suoi genitori. Fai un errore se non lo trovi. |
richiede: '^^ demoDirective' | Individua il controller di demoDirective cercando i genitori dell'elemento. Fai un errore se non lo trovi. |
richiede: '? ^ demoDirective' | Cerca di localizzare il controller di demoDirective cercando l'elemento ei suoi genitori o passa null al link fn se non trovato. |
richiede: '? ^^ demoDirective' | Cerca di localizzare il controller di demoDirective cercando i genitori dell'elemento o passa null al link fn se non lo trovi. |
Creare e consumare direttive personalizzate
Le direttive sono una delle funzionalità più potenti di angularjs. Le direttive angularjs personalizzate sono utilizzate per estendere la funzionalità di html creando nuovi elementi html o attributi personalizzati per fornire un determinato comportamento a un tag 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;
}
};
});
Questa direttiva può quindi essere utilizzata in App come:
<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>
Modello oggetto definizione direttiva
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
- impostato su true e tutti i nodi DOM tra l'inizio e la fine del nome della direttiva verranno raccolti e raggruppati come elementi direttivi -
priority
: consente di specificare l'ordine per applicare le direttive quando vengono definite più direttive su un singolo elemento DOM. Le direttive con numeri più alti vengono compilate per prime. -
terminal
- impostato su true e la priorità corrente sarà l'ultima serie di direttive da eseguire -
scope
: definisce il campo di applicazione della direttiva -
bind to controller
- associa le proprietà dell'ambito direttamente al controller di istruzioni -
controller
- funzione di costruzione del controller -
require
- richiede un'altra direttiva e inietta il suo controller come quarto argomento della funzione di collegamento -
controllerAs
- nome riferimento al controller nell'ambito della direttiva per consentire al controller di fare riferimento al modello di direttiva. -
restrict
- limita la direttiva a Element, Attribute, Class o Comment -
templateNameSpace
- imposta il tipo di documento utilizzato dal modello di direttiva: html, svg o math. html è l'impostazione predefinita -
template
- markup html che per impostazione predefinita sostituisce il contenuto dell'elemento della direttiva o avvolge il contenuto dell'elemento direttiva se transclude è true -
templateUrl
- url fornito in modo asincrono per il modello -
transclude
- Estrae il contenuto dell'elemento in cui appare la direttiva e lo mette a disposizione della direttiva. I contenuti sono compilati e forniti alla direttiva come funzione di inclusione. -
compile
- funzione per trasformare il DOM del template -
link
- usato solo se la proprietà compilata non è definita. La funzione di collegamento è responsabile della registrazione degli ascoltatori DOM e dell'aggiornamento del DOM. Viene eseguito dopo che il modello è stato clonato.
Esempio di direttiva di base
superman-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!')
});
}
}
});
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>
Puoi controllare di più sulle funzioni di restrict
e link
della direttiva sulla documentazione ufficiale di AngularJS sulle Direttive
Come creare un componente resuable usando la direttiva
Le direttive AngularJS sono ciò che controlla il rendering dell'HTML all'interno di un'applicazione AngularJS. Possono essere un elemento HTML, un attributo, una classe o un commento. Le direttive sono utilizzate per manipolare il DOM, associare un nuovo comportamento agli elementi HTML, l'associazione dei dati e molti altri. Alcuni esempi di direttive che fornisce angolare sono ng-model, ng-hide, ng-if.
Allo stesso modo si può creare la propria direttiva personalizzata e renderli resuable. Per creare direttive personalizzate Riferimento . L'idea che sta alla base della creazione di direttive riutilizzabili è quella di creare un insieme di direttive / componenti scritte da te proprio come angularjs ci fornisce usando angular.js. Queste direttive riutilizzabili possono essere particolarmente utili quando si dispone di una suite di applicazioni / applicazioni che richiede un comportamento, un aspetto e un comportamento coerenti. Un esempio di tale componente riutilizzabile può essere una semplice barra degli strumenti che potresti voler utilizzare nella tua applicazione o in diverse applicazioni, ma vuoi che si comportino allo stesso modo o abbiano lo stesso aspetto.
In primo luogo, crea una cartella denominata resuableComponents nella cartella dell'app e crea riusableModuleApp.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>
Le direttive sono componenti riutilizzabili per impostazione predefinita. Quando si apportano direttive in un modulo angolare separato, in realtà è esportabile e riutilizzabile tra le diverse applicazioni angolari. È possibile aggiungere semplicemente nuove direttive all'interno di reusableModuleApp.js e riusableModuleApp può avere il proprio controller, i servizi, l'oggetto DDO all'interno della direttiva per definire il comportamento.
Direttiva di base con modello e ambito isolato
La creazione di una direttiva personalizzata con un ambito isolato separerà l'ambito all'interno della direttiva dall'ambito esterno , al fine di evitare che la nostra direttiva modifichi accidentalmente i dati nell'ambito genitore e impedisca la lettura dei dati privati dall'ambito principale.
Per creare un ambito isolato e consentire ancora alla nostra direttiva personalizzata di comunicare con l'ambito esterno, possiamo usare l'opzione scope
che descrive come mappare i collegamenti dell'ambito interno della direttiva con l'ambito esterno.
I binding attuali sono realizzati con attributi aggiuntivi allegati alla direttiva. Le impostazioni di binding sono definite con l'opzione scope
e un oggetto con coppie chiave-valore:
- Una chiave , che corrisponde alla proprietà dell'ambito isolato della nostra direttiva
- Un valore che indica ad Angular come associare l'ambito interno della direttiva a un attributo corrispondente
Semplice esempio di una direttiva con un ambito isolato:
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);
Esempio di come utilizzare questa direttiva e collegare i dati dall'ambito del controller all'ambito interno della direttiva:
controller:
angular.module('app').controller('myCtrl', function($scope) {
$scope.currentProgressValue = 39;
$scope.maxProgressBarValue = 50;
});
Vista:
<div ng-controller="myCtrl">
<progress-bar current="currentProgressValue"></progress-bar>
<progress-bar current="currentProgressValue" max-value="maxProgressBarValue"></progress-bar>
</div>
Costruire un componente riutilizzabile
Le direttive possono essere utilizzate per costruire componenti riutilizzabili. Ecco un esempio di un componente "casella utente":
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>
user-box.html
<div>{{username}}</div>
<div>{{reputation}} reputation</div>
Il risultato sarà:
John Doe
1250 reputation
Andrew
2850 reputation
Decoratore della direttiva
A volte potresti aver bisogno di funzionalità aggiuntive da una direttiva. Invece di riscrivere (copiare) la direttiva, è possibile modificare il comportamento della direttiva.
Il decoratore verrà eseguito durante la fase $ iniettata.
Per farlo, prova un .config al tuo modulo. La direttiva si chiama myDirective, quindi devi configurare myDirectiveDirective. (questo in una convenzione angolare [leggi sui provider]).
Questo esempio cambierà templateUrl della direttiva:
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;
})
});
Questo esempio aggiunge un evento onClick all'elemento direttivo quando si fa clic, questo accade durante la fase di compilazione.
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;
});
});
Un approccio simile può essere utilizzato per provider e servizi.
Ereditarietà e interoperabilità della direttiva
Le direttive angolari js possono essere annidate o rese interoperabili.
In questo esempio, la direttiva Adir espone alla direttiva Bdir il suo controller $ scope, poiché Bdir richiede Adir.
angular.module('myApp',[]).directive('Adir', function () {
return {
restrict: 'AE',
controller: ['$scope', function ($scope) {
$scope.logFn = function (val) {
console.log(val);
}
}]
}
})
Assicurati di impostare richiede: '^ Adir' (guarda la documentazione angolare, alcune versioni non richiede ^ carattere).
.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.
});
}
}
}]);
Puoi annidare la tua direttiva in questo modo:
<div a-dir><span b-dir></span></div>
<a-dir><b-dir></b-dir> </a-dir>
Non è necessario che le direttive siano nidificate nel codice HTML.