Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/suissa/angularjs-directive-manual
:ng: Manual para Diretivas no AngularJs 1.x
https://github.com/suissa/angularjs-directive-manual
Last synced: about 2 months ago
JSON representation
:ng: Manual para Diretivas no AngularJs 1.x
- Host: GitHub
- URL: https://github.com/suissa/angularjs-directive-manual
- Owner: suissa
- License: mit
- Created: 2015-02-21T23:36:30.000Z (almost 10 years ago)
- Default Branch: master
- Last Pushed: 2016-11-03T09:03:04.000Z (about 8 years ago)
- Last Synced: 2024-04-10T21:19:03.935Z (9 months ago)
- Language: JavaScript
- Homepage:
- Size: 104 KB
- Stars: 164
- Watchers: 20
- Forks: 31
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
#AngularJS
![Logo do AngularJS](https://cldup.com/cWbFHP8Pol-1200x1200.png)
## ÍNDICE
- [Como criar](https://github.com/suissa/angularjs-directive-manual#como-criar)
- [API](https://github.com/suissa/angularjs-directive-manual#api)
- [restrict](https://github.com/suissa/angularjs-directive-manual#restrict)
- [replace](https://github.com/suissa/angularjs-directive-manual#replace)
- [template](https://github.com/suissa/angularjs-directive-manual#template)
- [templateUrl](https://github.com/suissa/angularjs-directive-manual#templateurl)
- [priority](https://github.com/suissa/angularjs-directive-manual#priority)
- [scope](https://github.com/suissa/angularjs-directive-manual#scope)
- [controller](https://github.com/suissa/angularjs-directive-manual#controller)
- [require](https://github.com/suissa/angularjs-directive-manual#require)
- [compile](https://github.com/suissa/angularjs-directive-manual#compile)
- [link](https://github.com/suissa/angularjs-directive-manual#link)
- [transculde](https://github.com/suissa/angularjs-directive-manual#transculde)## PRECISO ATUALIZAR PARA COMPONENTS DO 1.5
![Exército de clones](https://cldup.com/04QHfHjmPv.thumb.png)
##Directivas
As directivas são marcadores em um elemento DOM (como um atributo, o nome do elemento, comentário ou classe CSS) que informam ao compilador HTML do AngularJS ($compile) para anexar um comportamento específico para o elemento DOM ou mesmo transformar o elemento DOM e seus filhos.
Basicamente utilizamos as directivas para encapsular a lógica de apresentação de um módulo, qualquer tipo de interação no DOM deve ser feita única e exclusivamente na directiva, se você estiver fazendo isso no *Controller* tenho péssimas notícias para você.
![Você está errado, mas continue tentando.](https://cldup.com/kQb7cU5bJg-3000x3000.jpeg)
O AngularJS vem com um conjunto de directivas internas, como `ngBind`, `ngModel` e `ngClass`. Assim como você pode criar *Controllers* e *Services*, também pode criar suas próprias directivas para o Angular usar.
*O que significa "compilar" um template de HTML? Para AngularJS, "compilação" significa anexar listeners de eventos no HTML para torná-lo interativo.*
###Como criar?
![Como criar? Imagem da patente de uma campainha](http://chestofbooks.com/crafts/electricity/Electricity-For-Boys/images/Fig-49-Electric-Bell.png)
Já levando em consideração boas práticas esse é o código para iniciarmos a programação de uma directiva:
```js
(function () {var directive = function () {
return {};
};angular.module('moduleName')
.directive('directiveName', directive);}());
```No código anterior, a função `directive()` registra uma nova directiva em nosso módulo. O primeiro argumento para esta função é o nome da directiva. O segundo argumento é uma função que retorna um objeto de definição da directiva.
O segredo mora no que retornamos nesse objeto e para isso temos uma API para trabalhar com as directivas.
E todo o código foi encapsulado em uma [IIFE](http://benalman.com/news/2010/11/immediately-invoked-function-expression/) para que não haja "vazamentos" no módulo.
![WAT](https://cldup.com/I-XX4sQNwq.jpg)
Isso vazamento, para que seus dados não *vazem* para o escopo global, então com essa IIFE criamos um escopo local que nos garante o encapsulamento dos dados.
###API
A API da directiva pode ser um pouco complexa no início, mas com o tempo os conceitos vão se enraizando e começa a ficar um pouco mais fácil, vamos ver do que é composta essa API:
```js
',
var myModule = angular.module('moduleName');
myModule.directive('directiveName', function (injectables) {
return {
restrict: 'ACME',
template: '
templateUrl: 'directive.html',
replace: false,
priority: 0,
transclude: false,
scope: false,
terminal: false,
require: false,
controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },
compile: function compile(tElement, tAttrs, transclude) {
return {
pre: function preLink(scope, iElement, iAttrs, controller) { ... },
post: function postLink(scope, iElement, iAttrs, controller) { ... }
}
},
link: function postLink(scope, iElement, iAttrs) { ... }
};
});
```![Will falando THE FUCK?](https://cldup.com/zZtuN3sHf0-1200x1200.jpeg)
Ela pode assustar no começo mas nada que meses de estudo não nos ajude, vamos conhecer cada opção, porém começaremos com os mais utilizados.
Para iniciar usaremos esse exemplo simples de directiva:
```js
(function () {var directive = function () {
return {
restrict: 'AECM',
replace: 'true',
template: 'Hello World!!
'
};
};angular.module('moduleName')
.directive('helloWorld', directive);}());
```***
####restrictPara criar seu elemento da directiva, no template, podemos utilizar 4 formas diferentes:
- A: via atributo
- C: via classe
- M: via comentário
- E: via elemento##### A
```html
```##### C
```html
```##### M
```html
```
##### E
```html
```
> Para validar seu código em HTML5 use o prefixo **data**, exemplo: data-hello-world.
As mais comumente utilizadas são a `A` e `E` pois as de classe e comentário podem causar confusões em pessoas que não estão acostumadas com AngularJs e na minha opinião pessoal são péssimas para demonstrar que aquele código é uma directiva.
Exemplo: http://plnkr.co/edit/Wlnul9IGuDnZwOFjJdC3?p=preview
![eu não quero](http://memeblender.com/wp-content/uploads/2012/08/ecce-homo-jesus-painting-meme.jpg)
Perceba que o nome da directiva em camelCase, `helloWorld` pode ser usado das seguintes formas no template:
```html
```
###CUIDADO!
Caso você esteja usando o `restrict` como `E` dessa forma:
```html
```
```js
.directive("hello", function(){
return {
restrict: 'E',
template: 'Hello'
};
})
.directive("world", function(){
return {
restrict: 'E',
template: 'World'
};
})
```Exemplo: http://plnkr.co/edit/n9Az6LdPJjI9QQXtW8u1?p=preview
Ele não irá compilar corretamente mostrando apenas o `Hello`.
![](https://cldup.com/d6fnc_Dq9j-3000x3000.png)
Vamos ver como o HTML foi compilado:
```
Hello
```Então podemos perceber que ele terminou a compilação na primeira tag, que não foi corretamente fechada.
Discussão sobre em [https://github.com/angular/angular.js/issues/1953](https://github.com/angular/angular.js/issues/1953).
> self-closing or void elements as the html spec defines them are very special to the browser parser. you can't make your own, so for your custom elements you have to stick to non-void elements ().
>
> this can't be changed in angular. closing.**Dica:** se você deseja compor um elemento com mais de um comportamento, pode por exemplo agrupar directivas do tipo `A` em um único elemento.
```js
(function () {var directiveSuperman = function () {
return {
restrict: "A",
link: function(){
alert("Superman ao resgate!");
}
},
directiveFlash = function () {
return {
restrict: "A",
link: function(){
alert("FLASHHHHHHH!");
}
};
angular.module('moduleName')
.directive('superman', directiveSuperman)
.directive('flash', directiveFlash);}());
```Exemplo: [http://plnkr.co/edit/DPk8jazoAnpjFCdRampH?p=preview](http://plnkr.co/edit/DPk8jazoAnpjFCdRampH?p=preview)
***
####replaceUsado para especificar se o template gerado irá substituir o elemento HTML em que a directiva está ligada. No caso utilizando uma directiva como ` `, a substituição é definida como `true`. Assim, após a directiva ser compilada, o template produzido substitui . O resultado final é `
Hello World!!
`. Se você definir `replace` como `false`, o padrão, o template será inserido no elemento em que a directiva é invocada.O código gerado com `replace: false`:
```html
Hello World!!
```
E agora gerado com `replace: true`:
```html
Hello World!!
```Então ele basicamente substitui o seu elemento da directiva pelo resultado *compilado* dela. Com o `replace` setado como `true` você necessariamente precisa ter um elemento como raíz agrupando o conteúdo do template.
Exemplo correto:
```html
Hello World!
```Exemplo errado:
```html
Hello World!
```Exemplo: [http://plnkr.co/edit/0obL6YZJuGjGODh9yRLZ?p=preview](http://plnkr.co/edit/0obL6YZJuGjGODh9yRLZ?p=preview)
Caso você se depare com um erro assim:
```js
Template for directive 'directiveName' must have exactly one root element.
```Já sabe que é porque você não encapsulou seu template em uma tag.
Exemplo: [http://plnkr.co/edit/n9Az6LdPJjI9QQXtW8u1?p=preview](http://plnkr.co/edit/n9Az6LdPJjI9QQXtW8u1?p=preview)
![Fácil não?](https://cldup.com/KwOd022vK8-3000x3000.jpeg)
Mas em busca de mais material para estudar sobre esse atributo encontrei uma informação que diz que ele será depreciado.
> docs($compile): deprecate `replace` directives
> **BREAKING CHANGE:**> The `replace` flag for defining directives that replace the element that they are on will be removed in the next major angular version. This feature has difficult semantics (e.g. how attributes are merged) and leads to more problems compared to what it solves.
> Also, with WebComponents it is normal to have custom elements in the DOM.Então melhor se acostumar a deixar ele como `false`.
***
####templateDefine o conteúdo que deve ser usado pela directiva. Pode incluir HTML, expressões de data-binding e até mesmo outras directivas.
```js
(function () {var directive = function () {
return {
restrict: 'AECM',
template: 'Hello World!!
'
};
};angular.module('moduleName')
.directive('directiveName', directive);}());
```Para usarmos os valores de escopo do *Controller* onde a directiva está, precisamos apenas chamar a variável como no template:
```html
``````js
(function () {var directiveSuperman = function () {
return {
restrict: "A",
link: function(){
alert("Superman ao resgate!");
}
};
},
directiveFlash = function () {
return {
restrict: "A",
link: function(){
alert("Superman ao resgate!");
}
};
}angular.module('moduleName')
.directive('superman', directiveSuperman)
.directive('flash', directiveFlash);}());
```Exemplo: [http://plnkr.co/edit/kmHvPtrUTY6rQkU4seAI?p=preview](http://plnkr.co/edit/kmHvPtrUTY6rQkU4seAI?p=preview)
Também podemos utilizar outras directivas dentro, como por exemplo o `ng-repeat`:
```js
return {
restrict: 'AE',
template: '
- {{ l }}
};
```
E no *Controller* precisamos apenas setar o array `languages`:
```js
$scope.languages = ['javascript', 'php', 'python', 'ruby'];
```
Exemplo: [http://plnkr.co/edit/FkC9H2AtUEdMtUtJGDcv?p=preview](http://plnkr.co/edit/FkC9H2AtUEdMtUtJGDcv?p=preview)
***
####templateUrl
Fornece o caminho para o template que deve ser utilizado pela directiva. Aqui podemos tanto chamar um HTML como podemos chamar uma rota no servidor que sirva esse template renderizado, comumente utilizado em sistemas [MEAN](http://bemean.com.br/) onde o AngularJs consome uma *view* em Jade renderizada pelo Node.js e servida via Express por uma rota.
```js
return {
restrict: 'AE',
templateUrl: 'linguagens.html'
};
```
Ou acessando uma rota no servidor:
```js
return {
restrict: 'AE',
templateUrl: '/expose/linguagens'
};
```
Vamos passar a lógica que estava no nosso `template` para um arquivo HTML:
```html
- {{ l }}
```
Ou Jade:
```jade
ul
li(ng-repeat="l in languages"){{ l }}
```
***
####priority
![Tudo é prioridade](https://cldup.com/K2QgqX7BRL-1200x1200.jpeg)
Esta opção diz ao AngularJS para ordenar as directivas por prioridade, então uma directiva que tem maior prioridade será compilada ligadas antes das outras. A razão para ter essa opção é para podermos realizar seleção condicionada à saída da directiva compilada anteriormente.
No exemplo abaixo, eu quero adicionar classe `btn-primary` somente o elemento tem `btn` classe nele.
```js
.directive("btn", function(){
return {
restrict: 'A',
priority: 1,
link: function(scope, element, attrs) {
element.addClass('btn');
element.text('btn');
}
};
})
.directive("primary", function(){
return {
restrict: 'A',
priority: 0,
link: function(scope, element, attrs) {
if (element.hasClass('btn')) {
element.addClass('btn-primary');
element.text('btn-primary');
}
}
};
});
```
Exemplo: [http://plnkr.co/edit/S1oFSjk50Iq0zwQIDZ8R?p=preview](http://plnkr.co/edit/S1oFSjk50Iq0zwQIDZ8R?p=preview)
Agora ordenando corretamente a prioridade:
```js
app.directive("btn", function(){
return {
restrict: 'A',
priority: 1,
link: function(scope, element, attrs) {
element.addClass('btn');
element.text('btn');
}
};
});
app.directive("primary", function(){
return {
restrict: 'A',
priority: 2,
link: function(scope, element, attrs) {
if (element.hasClass('btn')) {
element.addClass('btn-primary');
element.text('btn-primary');
}
}
};
});
```
Exemplo: [http://plnkr.co/edit/YSxjvRzP8TK5BJos7inB?p=preview](http://plnkr.co/edit/YSxjvRzP8TK5BJos7inB?p=preview)
Você só deve usar essa propriedade caso uma directiva dependa da outra para algo.
***
####scope
É importante primeiro ter uma sólida compreensão da herança de protótipo do JavaScript, especialmente se você está vindo de um *background* de *backend* e você está mais familiarizado com a herança clássica. Então, vamos rever isso primeiro.
Suponha que parentScope tem as propriedades aString, aNumber, anArray, anObject e aFunction. Se childScope herda prototipicamente de parentScope, temos:
![](https://camo.githubusercontent.com/85ec776a0dd4acbe687f3db6367fa56872abb87f/687474703a2f2f692e737461636b2e696d6775722e636f6d2f61544147672e706e67)
Ao contrário dos outros frameworks MVC, AngularJS não tem classes ou funções específicas para a criação de *models*. Em vez disso, AngularJS estende os objetos JavaScript com métodos e propriedades personalizados. Esses objetos, também conhecidos como *scopes*, trabalham como uma cola entre a *view* e outras partes (*directives*, *controllers* e *services*) dentro da aplicação.
Quando a aplicação é iniciada, um objeto `rootScope` é criado. Cada *scope* criado por *directives*, *controllers* e *services* são prototipicamente herdados de rootScope.
Essa opção é usada para criar um novo *scope* filho ou um *scope* isolado, ela aceita 3 valores:
- false (padrão)
- true
- isolate (não esse valor, veremos logo abaixo)
***
#####scope: false
É a opção padrão a qual não cria um novo *scope* para a directiva, mas a faz compartilhar as propriedades com o *scope* pai, nesse caso o `$rootScope`.
```js
var app = angular.module('myapp', []);
app
.run(function($rootScope) {
$rootScope.autor = 'Ninguém';
})
.controller('MainCtrl', function($scope, $http, $rootScope) {
$scope.autor = 'Suissa';
})
.directive("comScopeFalse", function(){
return {
restrict: 'E',
scope: false,
template: 'Autor: {{$parent.autor}}'
};
});
```
Exemplo: http://plnkr.co/edit/tGPmiagxXLuDHup7rNqi?p=preview
***
#####scope: true
Cria um novo *scope*, mas prototipicamente herda o *scope* pai. Logo o seu *scope* pai será o *scope* do *Controller*, não o `$rootScope`.
```js
angular.module('myapp', []);
angular.module('myapp')
.run(function($rootScope) {
$rootScope.autor = 'Ninguém';
})
.controller('MainCtrl', function($scope, $http, $rootScope) {
$scope.autor = 'Suissa';
})
.directive("comScopeTrue", function(){
return {
restrict: 'E',
scope: true,
template: 'Autor: {{$parent.autor}}'
};
});
```
Exemplo: http://plnkr.co/edit/C0zlV1XnpbFHDPnbb5YS?p=preview
**#escrever sobre o scope.$parent**
***
#####scope: isolate
Cria um *scope* isolado que não herda prototipicamente do *scope* pai, mas você pode acessar o escopo pai usando scope.$parent.
> How can I then share the data between isolated scope and its parent scope as scope.$parent is not much useful in case of templates?
> Como eu posso compartilhar dados entre *scope* isolate e o *scope* pai?
Bem, *scope* isolado pega um objeto/hash que leva você às propriedades do *scope* pai e *binda* elas no *scope* local. Existem 3 formas de fazer isso:
- **@**: pega o valor do *scope* pai
- **=**: pega um valor passado via atributo para directiva
- **&**: *binda* uma expressão ou método que será executada no *scope* da directiva
@ – binds the value of parent scope property (which always a string) to the local scope. So the value you want to pass in should be wrapped in {{}}. Remember `a` in braces.
= – binds parent scope property directly which will be evaluated before being passed in.
& – binds an expression or method which will be executed in the context of the scope it belongs.
####terminal
####controller
Utilizado para definir o *Controller* que será associado ao template da directiva.
Pode ser tratada como uma sala de controle de directiva. Você pode vincular as propriedades/métodos para US $ âmbito disponível ou essa palavra-chave. Os dados ligados a este estará acessível em outras directivas, injetando o controlador usando exigir opção.
Você pode pensar nesse método como a sala de controle da directiva, você pode adicionar propriedades/métodos ao `$scope` desse *Controller* e ele pode ser acessado em outras directivas injetando o *Controller* usando a opção `require`.
No exemplo abaixo, vamos alternar o estado de uma lâmpada de modo que as directivas filhas saberão sobre o estado atual.
```js
return {
restrict: 'A',
controller: function($scope, $element, $attrs) {
$scope.state = true;
$scope.toggle = function() {
$scope.state = !$scope.state;
};
},
link: function($scope, element, attrs) {
angular.element(this).click(this.toggle);
}
};
```
E no HTML:
```html
lampada
{{state}}
```
Nesse exemplo criamos um *Controller* específico para essa directiva, onde adicionamos propriedade e método, esse o qual pôde ser chamado no método `link` para atrelar a função `toggle` ao evento de click desse elemento usando a directiva `ng-click="toggle()"`. Então a cada click nesse botão ele inverte o `$scope.state`, simples não?
Exemplo: [http://plnkr.co/edit/AYi0Fh9tsHo428DoMXZd?p=preview](http://plnkr.co/edit/AYi0Fh9tsHo428DoMXZd?p=preview)
Além de criamos um *Controller* para a directiva também podemos utilizar um já existente.
```html
```
```js
.controller('ProductCtrl', function($scope, $http) {
$scope.Product = { name: 'Produto teste',
price: 666,
description: 'Testando controller das directivas'};
})
.directive("produtoTitulo", function(){
return {
restrict: 'AE',
controller: 'ProductCtrl',
template: '
{{ Product.name }}
'};
})
.directive("produtoDescricao", function(){
return {
restrict: 'AE',
controller: 'ProductCtrl',
template: '
{{ Product.description }}
Preço: {{ Product.price }}
};
})
```
Nesse caso cada directiva recebe sua própria instância do *Controller*, porém estamos compartilhando a lógica entre elas e usando seus dados no template das directivas.
Exemplo: http://plnkr.co/edit/Yk2D9yD567Rh1McjNCzv?p=preview
Caso você queira compartilhar a mesma instância do *Controller* você deve usar o **require**.
***
####require
![](https://cldup.com/yMjyuh51Cq-2000x2000.jpeg)
Essa opção permite que você compartilhe a mesma instância do *Controller* em várias directivas.
O nome pode ser prefixado com:
> ? – Não acusará nenhum erro se a directiva mencionada não existir.
> ^ - Vai procurar pela directiva nos elementos pai, se não estiver disponível no mesmo elemento.
Use colchetes para requisitar múltiplas directivas:
> [‘directive1′, ‘directive2′, ‘directive3′]
**require: ngModel**
Quando você faz o require do ngModel, vem integrado com ele o ngModelController, que voce injeta na função link.
Quando você tem o ngModelController instanciado na sua função link, você pode se utilizar de todas as validações que o angular te dá. Ele pode ser útil quando você quiser encapsular inputs dentro da sua directive, e adicionar classes de css, mensagens de erro e outras tratamentos de erro(como eventos) pra caso a validação ocorra.
Ela possui outros diversos métodos, como:
- **$isEmpty(value)**: Faz a verificação pra ver se o valor do input é vazio ou não.
- **$setValidity(nomeValidacao,boolean)**: É usado pra adicionar/retirar validação de um campo. Se você utilizar o boolean como true, vai dizer que o campo está valido, e vice-versa.
- **$setPristine()**: Você pode utilizar esta função pra limpar seu campo, assim como a função $setDirty() pra "sujar" seu campo, porém a $setPristine() é mais comum.
- **$rollBackViewValue()**: Cancela a atualização e reseta o valor do input para que o valor do modelo não seja atualizado.
#### Parsers e Formatters
- **$parsers**: é um Array de funções que serão executadas uma atrás da outra toda vez que o valor da `VISÃO` mudar. É util para se utilizar de validações apenas na tela e por exemplo bloquear o botão de submit do usuário enquanto o formato que ele digitou não seja válido. Todas as funções do array tem que retornar o texto que será passado como parâmetro para a próxima funcão que vem em seguida. Caso o valor retornado por uma das funções seja undefined, significa que algum erro de javascript ocorreu.
-**$formatters**: é um array de funções que serão executadas uma atrás da outra toda vez que o valor do `MODELO`, ou seja, você pode utilizar os $formatters para validar caso receba algum dado de uma chamada REST, ou algo do tipo, porém eles não são tão utilizados quanto os $parsers.
-**$validators e $asyncValidators**: são 2 arrays que o ngModelController possui que mostram todos as funções de validação que o `model` tem. Os $asyncValidators óbviamente são para validações assíncronas.
As outras propriedades mostram o estado do seu input, como $pristine, caso não tenha sido alterado ainda, e coisas do tipo. Você pode ver a API completa [aqui](https://docs.angularjs.org/api/ng/type/ngModel.NgModelController).
O `ngModelController` não precisa ser utilizado necessariamente na directive. Vale lembrar também que apesar dele fazer a validação no front, isso não garante que o valor que será enviado para o seu back-end será valido, então é necessário validar nos dois.
***
####compile
![](http://www.angularjshub.com/code/examples/customdirectives/01_CompileLinkFunctions/images/directives-compile-link-calls.png)
A função `compile` recebe 2 parâmetros:
- $elem: é um objeto jqLite contendo o nó do DOM que está sendo compilado (então se a directiva estiver dentro de um elemento div, então o objeto jqLite é o nó que está dentro desse div)
- $attrs: é um objeto e cada atributo no nó do DOM corresponde a uma propriedade dentro do objeto attrs (note que o nome da propriedade é a versão normalizada do nome do atributo, por exemplo, se meu-atributo é especificado no nó DOM, em seguida, o objeto attrs terá a propriedade meuAtributo e seu valor será o valor real atribuído ao atributo no DOM)
Neste exemplo vamos ver como as directivas são processadas pelo AngularJS quando os encontra em um template HTML e como podemos escrever nossas próprias directivas personalizadas.
Exemplo: [http://plnkr.co/edit/B8zFNUcwARkjONxZhohX?p=preview](http://plnkr.co/edit/B8zFNUcwARkjONxZhohX?p=preview)
#####Fases de inicialização, compilação e linking
Quando AngularJS analisa o template HTML para processar as directivas, podemos identificar as três fases principais que cada directiva passa:
- inicialização: isso acontece quando uma directiva é encontrada pela primeira vez na passagem de árvore DOM (assim acontece apenas uma vez, mesmo que a directiva apareça várias vezes no template HTML) e permite que a directiva inicialize-se internamente, se necessário
- compilação: nesta fase o AngularJS manipula o DOM do template HTML e cada directiva tem uma chance de fazer algum processamento para cada nó em que ela aparece (por isso, se a mesma directiva aparece em vários nós DOM, a compilação da directiva será chamada para cada node); na fase de compilação de uma directiva também tem a chance de modificar o nó DOM antes de um escopo ser ligado a ele
- linking: nesta fase o AngularJS atribui *listeners* de eventos para o template HTML para torná-lo interativo e atribui um *scope* da directiva e ele faz isso para cada nó do DOM em que a directiva aparece; a fase de linking ocorre após a compilação de todo o template HTML executado
***
####link
Função usada para manipulação do DOM.
Exemplo de como manipular um elemento colocando uma cor de fundo nele via CSS.
```html
```
```js
return {
restrict: 'AE',
replace: true,
template: '
Hello World',
link: function($scope, $elem, $attrs) {
$elem.bind('click', function() {
$elem.css('background-color', 'white');
$scope.$apply(function() {
scope.color = "white";
});
});
$elem.bind('mouseover', function() {
$elem.css('cursor', 'pointer');
});
}
};
```
Como vemos a função `link` recebe 3 parâmetros:
- $scope: é o *scope* associado a nossa directiva
- $elem: é equivalente ao mesmo parâmetro a função `compile`
- $attrs: é equivalente ao mesmo parâmetro a função `compile`
E também podemos receber como quarto parâmetro um *Controller*.
***
####transclude
Pode haver um momento em que você quer que sua directiva "sobrescreva" o conteúdo existente de um elemento. Angular não só lhe permite fazer isso, mas também lhe dá um controle para inserir o DOM "transcluído" onde quiser usando a directiva ngTransclude.
- true
- element
#####true
Dentro da função de *compile*, você pode manipular o DOM com a ajuda da função de transclude ou você pode inserir o DOM "transcluído" para o template usando a directiva ngTransclude em qualquer tag HTML. Observe nossa antiga e adorada tag marquee:
```html
```
```js
angular.module('Diretivas', [])
.directive('whoiam', function($http) {
return {
restrict: 'A',
transclude: true,
templateUrl: 'whoiam.html',
link: function(scope, element, attrs) {
$http.get('https://api.github.com/repos/angular/angular.js')
.success(function(data) {
scope.data = data;
});
}
};
});
```
#####element
Essa opção "sobrescreve" todo o elemento e uma função transclude é introduzida na função de *compile*. Você não pode ter acesso ao *scope* aqui, pois o *scope* ainda não foi criado. A função *compile* cria uma função *link* para a directiva que tem acesso ao *scope* e transcludeFn permite tocar o elemento clonado (que foi "transcluído") para manipulação de DOM ou fazer uso de dados vinculados ao seu *scope*. Isso é usado em ng-repeat e ng-switch.
```js
angular.module('Diretivas', [])
.directive('transcludeElement', function() {
return {
restrict: 'A',
transclude: 'element',
compile: function($element, $attrs, transcludeFn) {
return function ($scope, el, $attrs) {
transcludeFn($scope, function cloneConnectFn(cElement) {
$element
.after('<h2>Eu fui adicionado durante compilação </h2>')
.after(cElement);
});
};
}
};
})
.directive('filho', function(){
return {
restrict: 'E',
link: function($scope, element, attrs) {
element.html(' com meu filho');
}
};
});
```