SlideShare uma empresa Scribd logo
1 de 53
AngularJS Directives 
10 passos para aprender a criar sua directivas
Os 10 Passos são: 
• 1 - Uma possível directiva? 
• 2 - Criando uma directiva com template inline. 
• 3 - Directiva com template externo e usando o restrict mode. 
• 4 - Criando um módulo para a directiva. 
• 5 - Outra view usando a mesma directiva. 
• 6 - Isolando o escopo da directiva. 
• 7 - Utilizando o Transclude. 
• 8 - Adicionando ações a directiva. 
• 9 - Criando uma controladora para a directiva. 
• 10 - Complicando a vida e criando directivas com dependência de outras directivas. 
@jandersonfc
Angular-seed 
https://github.com/angular/angular-seed 
@jandersonfc
1 - Uma possível directiva? 
View01.js 
View01.html 
@jandersonfc
2 - Criando uma directiva com template 
inline 
View02.js 
View02.html 
@jandersonfc
2 - Criando uma directiva com template 
Por padrão as directivas serão usadas como atributo 
View01.html 
<div card-profile></div> 
@jandersonfc 
inline
2 - Criando uma directiva com template 
Por padrão as directivas compartilham do mesmo escopo do 
parent. No nosso caso o scope da View02Ctrl. 
<div ng-repeat="user in users"> 
<div card-profile></div> 
</div> 
.directive('cardProfile', [function(){ 
return { 
template: '<h2>{{user.name}}</h2>n'+ 
'<p>Twitter: {{user.twitter}}</p>n'+ 
'<p>website: <a href="{{user.website}}">{{user.website}}</a></p>' 
}; 
}]) 
View02.html 
View02.js 
@jandersonfc 
inline
3 - Directiva com template externo e 
usando o restrict mode 
View03.js 
card-profile.html 
View03.html 
@jandersonfc
3 - Directiva com template externo e 
restrict indica como a directiva pode ser usada. 
Caso o valor do restrict seja ‘E’ a directiva só pode ser usada como Element. 
.directive('cardProfile2', [function(){ 
return { 
restrict: 'E', 
templateUrl: 'view03/card-profile.html' 
}; 
}]) 
View03.js 
<div ng-repeat="user in users"> 
<card-profile2></card-profile2> 
</div> 
View03.html 
@jandersonfc 
usando o restrict mode
3 - Directiva com template externo e 
restrict indica como a directiva pode ser usada. 
Caso o valor do restrict seja ‘A’ a directiva só pode ser usada como Attribute. 
.directive('cardProfile2', [function(){ 
return { 
restrict: 'A', 
templateUrl: 'view03/card-profile.html' 
}; 
}]) 
View03.js 
<div ng-repeat="user in users"> 
<div card-profile2></div> 
</div> 
View03.html 
@jandersonfc 
usando o restrict mode
3 - Directiva com template externo e 
restrict indica como a directiva pode ser usada. 
Caso o valor do restrict seja ‘C’ a directiva só pode ser usada como Class. 
.directive('cardProfile2', [function(){ 
return { 
restrict: 'C', 
templateUrl: 'view03/card-profile.html' 
}; 
}]) 
View03.js 
<div ng-repeat="user in users"> 
<div class="card-profile2"></div> 
</div> 
View03.html 
@jandersonfc 
usando o restrict mode
3 - Directiva com template externo e 
restrict indica como a directiva pode ser usada. 
Caso o valor do restrict seja ‘M’ a directiva só pode ser usada como Comment. 
.directive('cardProfile2', [function(){ 
return { 
restrict: 'M', 
templateUrl: 'view03/card-profile.html' 
}; 
}]) 
View03.js 
<div ng-repeat="user in users"> 
<!-- directive: card-profile2 --> 
</div> 
View03.html 
@jandersonfc 
usando o restrict mode
3 - Directiva com template externo e 
restrict indica como a directiva pode ser usada. 
Uma directiva pode ter mais de um restrict mode 
.directive('cardProfile2', [function(){ 
return { 
restrict: 'EACM', 
templateUrl: 'view03/card-profile.html' 
}; 
}]) 
View03.js 
@jandersonfc 
usando o restrict mode
3 - Directiva com template externo e 
templateUrl é usado para indicar o arquivo que essa 
directiva irá usar como template. 
.directive('cardProfile2', [function(){ 
return { 
restrict: 'M', 
templateUrl: 'view03/card-profile.html' 
}; 
}]) 
View03.js 
card-profile.html 
<h2>{{user.name}}</h2> 
<p>Twitter: {{user.twitter}}</p> 
<p>website: <a href="{{user.website}}">{{user.website}}</a></p> 
@jandersonfc 
usando o restrict mode
3 - Directiva com template externo e 
Dicas e Truques 
• Evite usar template externo desnecessário. O angular para usar esse template 
externo faz uma chamada http (GET). Isso é bem mais lento que deixar o template 
inline. 
• Template externo é bem mais legível, eu sei. Uma possibilidade é usar o 
templateCache. Assim você evitará múltiplas chamadas http desnecessários. Para 
saber mais sobre templateCache acesse 
https://docs.angularjs.org/api/ng/service/$templateCache . 
• Não existe uma regra para usar o restrict mode, é comum achar uma directiva com 
acesso 'use e abuse' (restrict: ‘EAC’). 
• É recomendável usar o restrict como Atributo ( restrict: 'A' ) quando sua directiva 
adicionar ou mudar o comportamento de um componente existente. (ex. <input 
validar-cpf />). 
• Quando sua directiva é um novo componente que adicionará novos elementos e 
comportamentos, recomenda-se usar Element ( restrict: ‘E' ). (ex. <card-profile /> ). 
@jandersonfc 
usando o restrict mode
4 - Criando um módulo para a directiva 
jfc-card-profile.js 
card-profile04.html 
View04.html 
@jandersonfc
4 - Criando um módulo para a directiva 
Basta adicionar o módulo para ter acesso as directivas. 
'use strict'; 
app.js 
// Declare app level module which 
depends on views, and components 
angular.module('myApp', [ 
'ngRoute', 
'myApp.view01', 
'myApp.view02', 
'myApp.view03', 
'myApp.view04', 
'myApp.view05', 
'myApp.view06', 
'myApp.view07', 
'myApp.view08', 
'myApp.view09', 
'myApp.view10', 
'myApp.version', 
'jfc' 
]) 
index.html 
<!-- In production use: 
<script 
src="//ajax.googleapis.com/ajax/libs/angularjs/x.x.x/angular.min.js"></script> 
--> 
<script src="bower_components/angular/angular.js"></script> 
<script src="bower_components/angular-route/angular-route.js"></script> 
<script src="app.js"></script> 
<script src="view01/view01.js"></script> 
<script src="view02/view02.js"></script> 
<script src="view03/view03.js"></script> 
<script src="view04/view04.js"></script> 
<script src="view05/view05.js"></script> 
<script src="view06/view06.js"></script> 
<script src="view07/view07.js"></script> 
<script src="view08/view08.js"></script> 
<script src="view09/view09.js"></script> 
<script src="view10/view10.js"></script> 
<script src="components/jfc-card-profile/jfc-card-profile.js"></script> 
<script src="components/version/version.js"></script> 
<script src="components/version/version-directive.js"></script> 
<script src="components/version/interpolate-filter.js"></script> 
@jandersonfc
4 - Criando um módulo para a directiva 
Basta adicionar o módulo para ter acesso as directivas. 
View04.html 
<p>This is the partial for view 4.</p> 
<p>criando um module para a directive para ser usado e N modules</p> 
<jfc-card-profile04></jfc-card-profile04> 
card-profile04.html.html 
<div ng-repeat="user in users"> 
<h2>{{user.name}}</h2> 
<p>Twitter: {{user.twitter}}</p> 
<p>website: <a href="{{user.website}}">{{user.website}}</a></p> 
</div> 
@jandersonfc
4 - Criando um módulo para a directiva 
Dicas e Truques 
• O Angular espera que o nome de sua directiva seja único. 
Caso você tenha duas directivas com o mesmo nome, 
mesmo sendo de módulos distintos, será lançado um erro. 
• É recomendável usar um identificador inicial em suas 
directivas (de 2 ou 3 caracteres) para evitar conflitos com 
outras directivas. (ex. jfcCardProfile ou brCardProfile no 
lugar de cardProfile). 
• Não é recomendável usar o identificador inicial ng , esse 
é o identificador usado nas directivas do próprio Angular. 
@jandersonfc
5 - Outra view usando a mesma directiva 
jfc-card-profile.js 
card-profile04.html 
View05.html 
@jandersonfc
6 - Isolando o escopo da directiva 
jfc-card-profile.js 
card-profile04.html 
View06.html 
@jandersonfc
6 - Isolando o escopo da directiva 
scope: {} indica que essa directiva terá seu próprio escopo. A directiva 
não terá mais acesso ao escopo do parent. Nossa directiva só terá acesso 
as variáveis de escopo informados em sua definição. 
jfc-card-profile.js 
.directive('jfcCardProfile06', [function(){ 
return { 
restrict: 'E', 
replace: true, 
templateUrl: 'components/jfc-card-profile/jfc-card-profile04.html', 
scope: { 
users: '=datas' 
} 
}; 
}]) 
View06.html 
<p>This is the partial for view 6.</p> 
<p>Isolando o Scope da Directive</p> 
<button ng-click="updateUsers()">Update Users</button> 
<jfc-card-profile06 datas="users"></jfc-card-profile06> 
@jandersonfc
6 - Isolando o escopo da directiva 
Se o nome do atributo preenchido no template for igual a variável de 
escopo que criamos em nossa directiva, podemos usar apenas o símbolo 
‘='. 
jfc-card-profile.js 
.directive('jfcCardProfile06', [function(){ 
return { 
restrict: 'E', 
replace: true, 
templateUrl: 'components/jfc-card-profile/jfc-card-profile04.html', 
scope: { 
users: '=' 
} 
}; 
}]) 
View06.html 
<p>This is the partial for view 6.</p> 
<p>Isolando o Scope da Directive</p> 
<button ng-click="updateUsers()">Update Users</button> 
<jfc-card-profile06 users="users"></jfc-card-profile06> 
@jandersonfc
6 - Isolando o escopo da directiva 
O valor '=' indica para a directiva um bi-direcional binding com o escopo 
do parent, ou seja, mudando o valor dessa variável na directiva mudará 
também no escopo externo(parent) e vice versa. 
.directive('jfcCardProfile06', [function(){ 
return { 
restrict: 'E', 
replace: true, 
templateUrl: 'components/jfc-card-profile/jfc-card-profile04.html', 
scope: { 
users: '=' 
} 
}; 
}]) 
jfc-card-profile.js 
@jandersonfc
6 - Isolando o escopo da directiva 
replace: true Vai substituir o elemento raiz da declaração da directiva e 
vai usar apenas os elementos da directiva. 
.directive('jfcCardProfile06', [function(){ 
return { 
restrict: 'E', 
replace: true, 
templateUrl: 'components/jfc-card-profile/jfc-card-profile04.html', 
scope: { 
users: '=' 
} 
}; 
}]) 
jfc-card-profile.js 
@jandersonfc
6 - Isolando o escopo da directiva 
replace: false 
<jfc-card-profile06 datas="users" class="ng-scope ng-isolate-scope”> 
<!-- ngRepeat: user in users —> 
<div ng-repeat="user in users" class="ng-scope"> 
<h2 class="ng-binding">Janderson Fernandes Cardoso</h2> 
<p class="ng-binding">Twitter: @jandersonfc</p> 
<p>website: <a href="http://jandersonfc.com" class="ng-binding">http://jandersonfc.com</a></p> 
replace: true 
</div><!-- end ngRepeat: user in users —> 
<div ng-repeat="user in users" class="ng-scope"> 
<h2 class="ng-binding">Janderson Futebol Clube</h2> 
<p class="ng-binding">Twitter: @jandersonfclube</p> 
<p>website: <a href="http://jandersonfclube.com" class="ng-binding">http://jandersonfclube.com</a></p> 
</div><!-- end ngRepeat: user in users —> 
</jfc-card-profile06> 
<!-- ngRepeat: user in users —> 
<div ng-repeat="user in users" class="ng-scope"> 
<h2 class="ng-binding">Janderson Fernandes Cardoso</h2> 
<p class="ng-binding">Twitter: @jandersonfc</p> 
<p>website: <a href="http://jandersonfc.com" class="ng-binding">http://jandersonfc.com</a></p> 
</div><!-- end ngRepeat: user in users —> 
<div ng-repeat="user in users" class="ng-scope"> 
<h2 class="ng-binding">Janderson Futebol Clube</h2> 
<p class="ng-binding">Twitter: @jandersonfclube</p> 
<p>website: <a href="http://jandersonfclube.com" class="ng-binding">http://jandersonfclube.com</a></p> 
</div><!-- end ngRepeat: user in users —> 
@jandersonfc
6 - Isolando o escopo da directiva 
Por que separar o nosso escopo? 
• Em nosso exemplo, era obrigatório ter uma variável 
chamada users no escopo do parent para a directiva 
funcionar. Separando o escopo e passando a informação 
por atributo resolvemos esse problema. 
• Isolar o escopo da directiva é o primeiro passo para criar 
directivas com reuso. 
• Separando o escopo garantimos que a directiva só tenha 
acesso as informações cruciais para seu funcionamento, 
sem correr o risco de alterar algo no escopo do parent 
acidentalmente. 
@jandersonfc
7 - Utilizando o Transclude 
jfc-card-profile.js 
card-profile07.html 
View07.html 
@jandersonfc
7 - Utilizando o Transclude 
transclude: true indica que a directiva irá extrair os elementos 
adicionados como "filhos" na declaração da directiva. Transclude é mais 
que isso, mas para facilitar a compreensão desses exemplos vamos no 
reter a essa explicação. 
<jfc-card-profile07 data="user"> 
<p>linkedin: <a href="{{user.linkedin}}">{{user.linkedin}}</a></p> 
<p>facebook: <a href="{{user.facebook}}">{{user.facebook}}</a></p> 
</jfc-card-profile07> 
View07.html 
.directive('jfcCardProfile07', [function(){ 
return { 
restrict: 'E', 
replace: true, 
transclude: true, 
templateUrl: 'components/jfc-card-profile/jfc-card-profile07.html', 
scope: { 
user: '=data' 
} 
}; 
}]) 
jfc-card-profile.js 
@jandersonfc
7 - Utilizando o Transclude 
<div> 
<h2>{{user.name}}</h2> 
<p>Twitter: {{user.twitter}}</p> 
<div ng-transclude></div> 
<p>website: <a href="{{user.website}}">{{user.website}}</a></p> 
</div> 
ng-transclude indica exatamente a posição onde os elementos que foram 
extraídos serão adicionados. 
jfc-card-profile07.html 
@jandersonfc
8 - Adicionando ações a directiva 
jfc-card-profile.js 
card-profile08.html 
@jandersonfc
8 - Adicionando ações a directiva 
view8.js 
view08.html 
@jandersonfc
8 - Adicionando ações a directiva 
É na função link que criaremos nossas variáveis, funções e manipulação de DOM necessários jfc-card-profile.js 
link: function(scope, element, attrs) { 
scope.edit = function(user){ 
user.editMode = true; 
} 
scope.save = function(user){ 
user.editMode = false; 
scope.onSave({user: user}); 
} 
} 
<div ng-repeat="user in users"> 
<p> 
<h2 ng-hide="user.editMode">{{user.name}}</h2> 
<input ng-show="user.editMode" ng-model="user.name"/> 
</p> 
<p> 
<span ng-hide="user.editMode">Twitter: {{user.twitter}}</span> 
<input ng-show="user.editMode" ng-model="user.twitter"/> 
</p> 
<p> 
<span ng-hide="user.editMode">website: <a 
href="{{user.website}}">{{user.website}}</a></span> 
<input ng-show="user.editMode" ng-model="user.website"/> 
</p> 
<button ng-hide="user.editMode" ng-click=" 
edit(user)">Edit</button> 
<button ng-show="user.editMode" ng-click=" 
save(user)">Save</button> 
</div> 
jfc-card-profile08.html 
@jandersonfc
8 - Adicionando ações a directiva 
link: function(scope, element, attrs) { 
• scope - Equivalente ao $scope das controladoras, objeto que 
contém nossas variáveis e funções acessíveis ao template. 
• element - Representa o jqlite-wrapped do elemento html da nossa 
directiva, não é necessário usar o $ do jQuery para manipular 
esse elemento, o angular já traz ele pronto para isso. É muito 
comum manipular esse elemento quando a directiva é uma forma 
de usar um plugin jQuery, ou quando queremos adicionar event 
listeners nesse elemento. (ex. element.datepicker(), 
element.on('mousedown', function(event) ) 
• attrs - traz a lista de atributos e seus valores adicionados na 
nossa directiva. (ex. <input my-directive min="23" max=“24” />) 
@jandersonfc
8 - Adicionando ações a directiva 
Escopo com ‘&’ indica uma expressão, no nosso caso passamos uma 
função que servirá de callback, veja abaixo: 
jfc-card-profile.js 
.directive('jfcCardProfile08', [function(){ 
return { 
restrict: 'E', 
replace: true, 
transclude: true, 
templateUrl: 'components/jfc-card-profile/jfc-card- 
profile08.html', 
scope: { 
users: '=datas', 
onSave: '&' 
}, 
link: function(scope, element, attrs) { 
scope.edit = function(user){ 
user.editMode = true; 
} 
scope.save = function(user){ 
user.editMode = false; 
scope.onSave({user: user}); 
} 
} 
}; 
}]) 
view08.html 
<jfc-card-profile08 datas="users" on-save=“saveUser(user)"> 
</jfc-card-profile08> 
view08.js 
.controller('View08Ctrl', ['$scope', function($scope) { 
$scope.users = [ 
{ 
name: 'Janderson Fernandes Cardoso', 
twitter: '@jandersonfc', 
website: 'http://jandersonfc.com' 
}, 
{ 
name: 'Janderson Futebol Clube', 
twitter: '@jandersonfclube', 
website: 'http://jandersonfclube.com' 
} 
]; 
$scope.saveUser = function (user){ 
console.log('call resource for example'); 
console.log(user); 
} 
}]); 
@jandersonfc
8 - Adicionando ações a directiva 
Dicas e Truques 
• Existe a função compile na directiva. na execução do 
compile existe a chamada para as funções preLink e 
postLink. 
• A função link é equivalente ao postLink do compile. 
• Ao usar o compile não utilizar a função link. 
• Não é recomendável usar a função compile, somente 
em caso de performance onde será necessário 
executar alguma rotina antes do postLink. 
@jandersonfc
9 - Criando uma controladora para a 
directiva 
jfc-card-profile.js 
@jandersonfc
9 - Criando uma controladora para a 
Quando criamos uma controller , ela é instanciada antes da execução da 
funçao preLink em compile. 
controller: function($scope) { 
$scope.setEditModeToFalse = function(){ 
for (var i = 0; i < $scope.users.length; i++) { 
$scope.users[i].editMode = false; 
}; 
} 
$scope.edit = function(user){ 
user.editMode = true; 
} 
$scope.save = function(user){ 
user.editMode = false; 
$scope.onSave({user: user}); 
} 
}, 
link: function(scope, element, attrs) { 
scope.setEditModeToFalse(); 
} 
jfc-card-profile.js 
@jandersonfc 
directiva
9 - Criando uma controladora para a 
Dicas e Truques 
• Usar Controladora parece ser uma ótima forma de 
organizar o código da directiva, deixando a lógica de 
manipulação de scope na controller e manipulação de 
DOM na função link . 
• Na documentação do Angular só é recomendado usar 
controladora quando você quer expor a API de sua directiva 
para outras directivas (veremos como isso funciona no 
exemplo 10). 
• Portanto, no exemplo 09, não é recomendável usar a 
função controller, nesse caso é melhor fazer diretamente 
na função link como no exemplo 08. 
@jandersonfc 
directiva
10 - Complicando a vida e criando directivas 
com dependência de outras directivas 
view10.html 
jfc-card-profile.js 
jfc-card-profile10-list.html 
@jandersonfc
10 - Complicando a vida e criando directivas 
com dependência de outras directivas 
jfc-card-profile10-renderer.html 
jfc-card-profile.js 
@jandersonfc
10 - Complicando a vida e criando directivas 
com dependência de outras directivas 
jfc-card-profile.js 
jfc-card-profile10-view.html 
@jandersonfc
10 - Complicando a vida e criando directivas 
com dependência de outras directivas 
jfc-card-profile.js 
jfc-card-profile10-edit.html 
@jandersonfc
10 - Complicando a vida e criando directivas 
com dependência de outras directivas 
Podemos criar directivas que possuem outras directivas 
jfc-card-profile10-list.html 
<jfc-card-profile10-renderer ng-repeat="user in 
users" 
ng-switch on="user.mode"> 
</jfc-card-profile10-renderer> 
@jandersonfc
10 - Complicando a vida e criando directivas 
com dependência de outras directivas 
A controladora pode ser declarada diretamente na directivas como fizemos no 
exemplo 09 ou referenciar uma controller existente no módulo. 
.controller('cardProfileController', ['$scope', '$attrs', function($scope, $attrs){ 
this.setModeDefault = function(){ 
$scope.user.mode = 'view'; 
} 
this.edit = function(){ 
$scope.user.mode = 'edit'; 
} 
this.save = function(){ 
$scope.user.mode = 'view'; 
$scope.onSave({user: $scope.user}); 
} 
}]) 
.directive('jfcCardProfile10Renderer', function(){ 
return { 
restrict: 'E', 
replace: false, 
controller: 'cardProfileController', 
templateUrl: 'components/jfc-card-profile/jfc-card-profile10-renderer.html', 
link: function(scope, element, attrs, ctrl) { 
ctrl.setModeDefault(); 
} 
}; 
}) 
jfc-card-profile.js 
@jandersonfc
10 - Complicando a vida e criando directivas 
com dependência de outras directivas 
A controladora da directiva pode ser acessada através do quarto parâmetro na 
declaração da função link. 
.controller('cardProfileController', ['$scope', '$attrs', function($scope, $attrs){ 
this.setModeDefault = function(){ 
$scope.user.mode = 'view'; 
} 
this.edit = function(){ 
$scope.user.mode = 'edit'; 
} 
this.save = function(){ 
$scope.user.mode = 'view'; 
$scope.onSave({user: $scope.user}); 
} 
}]) 
.directive('jfcCardProfile10Renderer', function(){ 
return { 
restrict: 'E', 
replace: false, 
controller: 'cardProfileController', 
templateUrl: 'components/jfc-card-profile/jfc-card-profile10-renderer.html', 
link: function(scope, element, attrs, ctrl) { 
ctrl.setModeDefault(); 
} 
}; 
}) 
jfc-card-profile.js 
@jandersonfc
10 - Complicando a vida e criando directivas 
com dependência de outras directivas 
ng-switch é uma diretiva do angular que você pode usar para facilitar a troca de 
estrutura de DOM. 
jfc-card-profile10-list.html 
<jfc-card-profile10-renderer ng-repeat="user in users" 
ng-switch on="user.mode"> 
</jfc-card-profile10-renderer> 
jfc-card-profile10-renderer.html 
<jfc-card-profile10-view ng-switch-when="view"></jfc-card-profile10-view> 
<jfc-card-profile10-edit ng-switch-when="edit"></jfc-card-profile10-edit> 
@jandersonfc
10 - Complicando a vida e criando directivas 
com dependência de outras directivas 
Nossa directiva Renderer adiciona mais duas directivas em nosso projeto. View 
e Edit. 
jfc-card-profile10-renderer.html 
<jfc-card-profile10-view ng-switch-when="view"></jfc-card-profile10-view> 
<jfc-card-profile10-edit ng-switch-when="edit"></jfc-card-profile10-edit> 
@jandersonfc
10 - Complicando a vida e criando directivas 
com dependência de outras directivas 
Nossa directiva View compartilha da mesma controladora que a Renderer. para isso usamos o atributo 
require. O símbolo ^ indica que é obrigatório que jfcCardProfile10Renderer seja declarada em um parent 
element e que a mesma possua uma controladora. Existem outros símbolos que podem ser passados no 
require ( ?, ^^, ?^, ?^^ ). Olhe a documentação para mais detalhes. 
jfc-card-profile10.js 
.directive('jfcCardProfile10View', function(){ 
return { 
restrict: 'E', 
replace: true, 
templateUrl: 'components/jfc-card-profile/jfc-card-profile10-view.html', 
require: '^jfcCardProfile10Renderer', 
link: function(scope, element, attrs, ctrl) { 
scope.edit = function(){ 
ctrl.edit(); 
} 
} 
}; 
}) 
@jandersonfc
10 - Complicando a vida e criando directivas 
com dependência de outras directivas 
Agora que nossa directiva View compartilha da mesma controller da Renderer. Podemos acessar nossa 
controladora através do quarto parâmetro. 
jfc-card-profile10.js 
.directive('jfcCardProfile10View', function(){ 
return { 
restrict: 'E', 
replace: true, 
templateUrl: 'components/jfc-card-profile/jfc-card-profile10-view.html', 
require: '^jfcCardProfile10Renderer', 
link: function(scope, element, attrs, ctrl) { 
scope.edit = function(){ 
ctrl.edit(); 
} 
} 
}; 
}) 
@jandersonfc
10 - Complicando a vida e criando directivas 
com dependência de outras directivas 
O mesmo acontece com nossa diretiva Edit. 
jfc-card-profile10.js 
.directive('jfcCardProfile10Edit', function(){ 
return { 
restrict: 'E', 
replace: true, 
templateUrl: 'components/jfc-card-profile/jfc-card-profile10-edit.html', 
require: '^jfcCardProfile10Renderer', 
link: function(scope, element, attrs, ctrl) { 
scope.save = function(){ 
ctrl.save(); 
} 
} 
}; 
}); 
@jandersonfc
E agora? 
• Pense 2 vezes antes de criar um directiva. Evite criar directivas desnecessárias. 
• Directiva é sempre muito útil, mas isso não significa que a forma como é criada hoje seja 
prática. Por isso, evite criar directivas desnecessárias. 
• No AngularJS 2 terá uma grande mudança na forma de criar directivas, e isso é muito 
bom! então evite criar directivas desnecessárias. 
• Polymer é outro projeto do Google que trabalha já com os Web Components. Não tenho 
dúvida que web components é a melhor forma de criar componentes. Polymer terá 
integração garantida no AngulaJS 2. Por favor, evite criar directivas desnecessárias. 
• Essa apresentação e todo o material de apoio foi criado se baseando unicamente na 
excelente documentação do AngularJS ( https://docs.angularjs.org/guide/directive ). 
Mesmo assim, evite criar directivas desnecessárias. :P 
• O material de apoio dessa apresentação pode ser acessada em 
https://github.com/jandersonfc/tutorial-angularjs-directives 
@jandersonfc
Obrigado! 
http://www.jandersonfc.com 
@jandersonfc

Mais conteúdo relacionado

Mais procurados

Javascript truquesmagicos
Javascript truquesmagicosJavascript truquesmagicos
Javascript truquesmagicos
ponto hacker
 
Técnicas de Refactorización (EN ESPANOL)
Técnicas de Refactorización (EN ESPANOL)Técnicas de Refactorización (EN ESPANOL)
Técnicas de Refactorización (EN ESPANOL)
Rodrigo Branas
 
Spring MVC Framework
Spring MVC FrameworkSpring MVC Framework
Spring MVC Framework
elliando dias
 
ASP.NET MVC Mini Curso
ASP.NET MVC Mini CursoASP.NET MVC Mini Curso
ASP.NET MVC Mini Curso
Vinicius Rocha
 

Mais procurados (20)

JSF 2.0 e ScrumToys
JSF 2.0 e ScrumToysJSF 2.0 e ScrumToys
JSF 2.0 e ScrumToys
 
Spa com angular js flisol 2015 - aquidauana ms
Spa com angular js   flisol 2015 - aquidauana msSpa com angular js   flisol 2015 - aquidauana ms
Spa com angular js flisol 2015 - aquidauana ms
 
Técnicas de Refactoring
Técnicas de RefactoringTécnicas de Refactoring
Técnicas de Refactoring
 
Javascript truquesmagicos
Javascript truquesmagicosJavascript truquesmagicos
Javascript truquesmagicos
 
Técnicas de Refactorización (EN ESPANOL)
Técnicas de Refactorización (EN ESPANOL)Técnicas de Refactorización (EN ESPANOL)
Técnicas de Refactorización (EN ESPANOL)
 
JSF 2.0 e ScrumToys
JSF 2.0 e ScrumToysJSF 2.0 e ScrumToys
JSF 2.0 e ScrumToys
 
Facelets
FaceletsFacelets
Facelets
 
Autenticação com AngularJS e loadOnDemand
Autenticação com AngularJS e loadOnDemandAutenticação com AngularJS e loadOnDemand
Autenticação com AngularJS e loadOnDemand
 
Desenvolvimento de Aplicações Web AngularJS no Contexto da IoT
Desenvolvimento de Aplicações Web AngularJS no Contexto da IoTDesenvolvimento de Aplicações Web AngularJS no Contexto da IoT
Desenvolvimento de Aplicações Web AngularJS no Contexto da IoT
 
Apresentação angular js
Apresentação angular jsApresentação angular js
Apresentação angular js
 
Produtividade com JavaServer Faces
Produtividade com JavaServer FacesProdutividade com JavaServer Faces
Produtividade com JavaServer Faces
 
Construindo Sistemas Com Django
Construindo Sistemas Com DjangoConstruindo Sistemas Com Django
Construindo Sistemas Com Django
 
Aula 07 acessibilidade
Aula 07  acessibilidadeAula 07  acessibilidade
Aula 07 acessibilidade
 
Desenvolvendo aplicações web com o framework cakephp
Desenvolvendo aplicações web com o framework cakephpDesenvolvendo aplicações web com o framework cakephp
Desenvolvendo aplicações web com o framework cakephp
 
Curso de Desenvolvimento Web - Módulo 03 - JavaScript
Curso de Desenvolvimento Web - Módulo 03 - JavaScriptCurso de Desenvolvimento Web - Módulo 03 - JavaScript
Curso de Desenvolvimento Web - Módulo 03 - JavaScript
 
Criando um Web Service Restful com Jersey, Eclipse, JBoss, Tomcat, WebSphere
Criando um Web Service Restful com Jersey, Eclipse, JBoss, Tomcat, WebSphereCriando um Web Service Restful com Jersey, Eclipse, JBoss, Tomcat, WebSphere
Criando um Web Service Restful com Jersey, Eclipse, JBoss, Tomcat, WebSphere
 
Clean Code
Clean CodeClean Code
Clean Code
 
Desenvolvendo aplicacoes mobile_com_html_css_
Desenvolvendo aplicacoes mobile_com_html_css_Desenvolvendo aplicacoes mobile_com_html_css_
Desenvolvendo aplicacoes mobile_com_html_css_
 
Spring MVC Framework
Spring MVC FrameworkSpring MVC Framework
Spring MVC Framework
 
ASP.NET MVC Mini Curso
ASP.NET MVC Mini CursoASP.NET MVC Mini Curso
ASP.NET MVC Mini Curso
 

Destaque

Destaque (20)

The New Age Business Analyst - Role of BA in the Changing times of Agile Soft...
The New Age Business Analyst - Role of BA in the Changing times of Agile Soft...The New Age Business Analyst - Role of BA in the Changing times of Agile Soft...
The New Age Business Analyst - Role of BA in the Changing times of Agile Soft...
 
HTTP Interceptors com AngularJS
HTTP Interceptors com AngularJSHTTP Interceptors com AngularJS
HTTP Interceptors com AngularJS
 
Introdução ao AngularJS
Introdução ao AngularJSIntrodução ao AngularJS
Introdução ao AngularJS
 
Realtime com node.js e socket.io
Realtime com node.js e socket.ioRealtime com node.js e socket.io
Realtime com node.js e socket.io
 
Node.js - #3 - Global Objects - Rodrigo Branas
Node.js - #3 - Global Objects - Rodrigo BranasNode.js - #3 - Global Objects - Rodrigo Branas
Node.js - #3 - Global Objects - Rodrigo Branas
 
Node.js - #4 - Timers - Rodrigo Branas
Node.js - #4 - Timers - Rodrigo BranasNode.js - #4 - Timers - Rodrigo Branas
Node.js - #4 - Timers - Rodrigo Branas
 
Node.js - #1 - Introdução - Rodrigo Branas
Node.js - #1 - Introdução - Rodrigo BranasNode.js - #1 - Introdução - Rodrigo Branas
Node.js - #1 - Introdução - Rodrigo Branas
 
Node.js - #5 - Process - Rodrigo Branas
Node.js - #5 - Process - Rodrigo BranasNode.js - #5 - Process - Rodrigo Branas
Node.js - #5 - Process - Rodrigo Branas
 
Node.js - #6 - Core Modules - net - Rodrigo Branas
Node.js - #6 - Core Modules - net - Rodrigo BranasNode.js - #6 - Core Modules - net - Rodrigo Branas
Node.js - #6 - Core Modules - net - Rodrigo Branas
 
Node.js - #2 - Sistema de Módulos - Rodrigo Branas
Node.js - #2 - Sistema de Módulos - Rodrigo BranasNode.js - #2 - Sistema de Módulos - Rodrigo Branas
Node.js - #2 - Sistema de Módulos - Rodrigo Branas
 
Iniciando com jQuery
Iniciando com jQueryIniciando com jQuery
Iniciando com jQuery
 
Curso AngularJS - 2. conceptos básicos
Curso AngularJS - 2. conceptos básicosCurso AngularJS - 2. conceptos básicos
Curso AngularJS - 2. conceptos básicos
 
Curso AngularJS - 3. módulos y controladores
Curso AngularJS - 3. módulos y controladoresCurso AngularJS - 3. módulos y controladores
Curso AngularJS - 3. módulos y controladores
 
Curso AngularJS - 1. introducción
Curso AngularJS - 1. introducciónCurso AngularJS - 1. introducción
Curso AngularJS - 1. introducción
 
Curso AngularJS - 7. temas avanzados
Curso AngularJS - 7. temas avanzadosCurso AngularJS - 7. temas avanzados
Curso AngularJS - 7. temas avanzados
 
Introdução ao AngularJS!
Introdução ao AngularJS!Introdução ao AngularJS!
Introdução ao AngularJS!
 
Tutorial AngularJS - episódio 5 - diretivas
Tutorial AngularJS - episódio 5 -  diretivasTutorial AngularJS - episódio 5 -  diretivas
Tutorial AngularJS - episódio 5 - diretivas
 
JavaScript - Date
JavaScript - DateJavaScript - Date
JavaScript - Date
 
O Poderoso AngularJS
O Poderoso AngularJSO Poderoso AngularJS
O Poderoso AngularJS
 
Angular js
Angular jsAngular js
Angular js
 

Semelhante a AngularJS - 10 passos para aprender a criar suas directivas

Trabalho ProgramaçãO Comercial Ii
Trabalho ProgramaçãO Comercial IiTrabalho ProgramaçãO Comercial Ii
Trabalho ProgramaçãO Comercial Ii
Mateus Ramos Pereira
 

Semelhante a AngularJS - 10 passos para aprender a criar suas directivas (20)

Backbone.js nas trincheiras
Backbone.js nas trincheirasBackbone.js nas trincheiras
Backbone.js nas trincheiras
 
Como Perder Peso (no browser)
Como Perder Peso (no browser)Como Perder Peso (no browser)
Como Perder Peso (no browser)
 
Estrutura do Projeto
Estrutura do ProjetoEstrutura do Projeto
Estrutura do Projeto
 
Estrutura do Projeto
Estrutura do ProjetoEstrutura do Projeto
Estrutura do Projeto
 
ZF2 básico : Desenvolvendo um Blog com o Zend Framework 2
ZF2 básico : Desenvolvendo um Blog com o Zend Framework 2ZF2 básico : Desenvolvendo um Blog com o Zend Framework 2
ZF2 básico : Desenvolvendo um Blog com o Zend Framework 2
 
Django Módulo Básico Parte II
Django Módulo Básico Parte IIDjango Módulo Básico Parte II
Django Módulo Básico Parte II
 
Componentes para a Web
Componentes para a WebComponentes para a Web
Componentes para a Web
 
LambdaDay: Backbone.js
LambdaDay: Backbone.jsLambdaDay: Backbone.js
LambdaDay: Backbone.js
 
Como escolher o Framework Java para web?
Como escolher o Framework Java para web?Como escolher o Framework Java para web?
Como escolher o Framework Java para web?
 
Programando para programadores: Desafios na evolução de um Framework
Programando para programadores: Desafios na evolução de um FrameworkProgramando para programadores: Desafios na evolução de um Framework
Programando para programadores: Desafios na evolução de um Framework
 
Zend Framework
Zend FrameworkZend Framework
Zend Framework
 
Django: Desenvolvendo uma aplicação web em minutos
Django: Desenvolvendo uma aplicação web em minutosDjango: Desenvolvendo uma aplicação web em minutos
Django: Desenvolvendo uma aplicação web em minutos
 
AngularJS com loadOnDemand
AngularJS com loadOnDemandAngularJS com loadOnDemand
AngularJS com loadOnDemand
 
TechDay - Sistemas WEB em Java - Rogério N. Jr.
TechDay - Sistemas WEB em Java - Rogério N. Jr.TechDay - Sistemas WEB em Java - Rogério N. Jr.
TechDay - Sistemas WEB em Java - Rogério N. Jr.
 
Workshop Node.js + MongoDB + Mongoose
Workshop Node.js + MongoDB + MongooseWorkshop Node.js + MongoDB + Mongoose
Workshop Node.js + MongoDB + Mongoose
 
Trabalho ProgramaçãO Comercial Ii
Trabalho ProgramaçãO Comercial IiTrabalho ProgramaçãO Comercial Ii
Trabalho ProgramaçãO Comercial Ii
 
ASP.NET MVC
ASP.NET MVCASP.NET MVC
ASP.NET MVC
 
Treinamento Play Framework
Treinamento Play FrameworkTreinamento Play Framework
Treinamento Play Framework
 
Google Analytics Reporting API: Bebendo água direto da fonte
Google Analytics Reporting API: Bebendo água direto da fonteGoogle Analytics Reporting API: Bebendo água direto da fonte
Google Analytics Reporting API: Bebendo água direto da fonte
 
Quick Form DataBase (QFDB)
Quick Form DataBase (QFDB)Quick Form DataBase (QFDB)
Quick Form DataBase (QFDB)
 

AngularJS - 10 passos para aprender a criar suas directivas

  • 1. AngularJS Directives 10 passos para aprender a criar sua directivas
  • 2. Os 10 Passos são: • 1 - Uma possível directiva? • 2 - Criando uma directiva com template inline. • 3 - Directiva com template externo e usando o restrict mode. • 4 - Criando um módulo para a directiva. • 5 - Outra view usando a mesma directiva. • 6 - Isolando o escopo da directiva. • 7 - Utilizando o Transclude. • 8 - Adicionando ações a directiva. • 9 - Criando uma controladora para a directiva. • 10 - Complicando a vida e criando directivas com dependência de outras directivas. @jandersonfc
  • 4. 1 - Uma possível directiva? View01.js View01.html @jandersonfc
  • 5. 2 - Criando uma directiva com template inline View02.js View02.html @jandersonfc
  • 6. 2 - Criando uma directiva com template Por padrão as directivas serão usadas como atributo View01.html <div card-profile></div> @jandersonfc inline
  • 7. 2 - Criando uma directiva com template Por padrão as directivas compartilham do mesmo escopo do parent. No nosso caso o scope da View02Ctrl. <div ng-repeat="user in users"> <div card-profile></div> </div> .directive('cardProfile', [function(){ return { template: '<h2>{{user.name}}</h2>n'+ '<p>Twitter: {{user.twitter}}</p>n'+ '<p>website: <a href="{{user.website}}">{{user.website}}</a></p>' }; }]) View02.html View02.js @jandersonfc inline
  • 8. 3 - Directiva com template externo e usando o restrict mode View03.js card-profile.html View03.html @jandersonfc
  • 9. 3 - Directiva com template externo e restrict indica como a directiva pode ser usada. Caso o valor do restrict seja ‘E’ a directiva só pode ser usada como Element. .directive('cardProfile2', [function(){ return { restrict: 'E', templateUrl: 'view03/card-profile.html' }; }]) View03.js <div ng-repeat="user in users"> <card-profile2></card-profile2> </div> View03.html @jandersonfc usando o restrict mode
  • 10. 3 - Directiva com template externo e restrict indica como a directiva pode ser usada. Caso o valor do restrict seja ‘A’ a directiva só pode ser usada como Attribute. .directive('cardProfile2', [function(){ return { restrict: 'A', templateUrl: 'view03/card-profile.html' }; }]) View03.js <div ng-repeat="user in users"> <div card-profile2></div> </div> View03.html @jandersonfc usando o restrict mode
  • 11. 3 - Directiva com template externo e restrict indica como a directiva pode ser usada. Caso o valor do restrict seja ‘C’ a directiva só pode ser usada como Class. .directive('cardProfile2', [function(){ return { restrict: 'C', templateUrl: 'view03/card-profile.html' }; }]) View03.js <div ng-repeat="user in users"> <div class="card-profile2"></div> </div> View03.html @jandersonfc usando o restrict mode
  • 12. 3 - Directiva com template externo e restrict indica como a directiva pode ser usada. Caso o valor do restrict seja ‘M’ a directiva só pode ser usada como Comment. .directive('cardProfile2', [function(){ return { restrict: 'M', templateUrl: 'view03/card-profile.html' }; }]) View03.js <div ng-repeat="user in users"> <!-- directive: card-profile2 --> </div> View03.html @jandersonfc usando o restrict mode
  • 13. 3 - Directiva com template externo e restrict indica como a directiva pode ser usada. Uma directiva pode ter mais de um restrict mode .directive('cardProfile2', [function(){ return { restrict: 'EACM', templateUrl: 'view03/card-profile.html' }; }]) View03.js @jandersonfc usando o restrict mode
  • 14. 3 - Directiva com template externo e templateUrl é usado para indicar o arquivo que essa directiva irá usar como template. .directive('cardProfile2', [function(){ return { restrict: 'M', templateUrl: 'view03/card-profile.html' }; }]) View03.js card-profile.html <h2>{{user.name}}</h2> <p>Twitter: {{user.twitter}}</p> <p>website: <a href="{{user.website}}">{{user.website}}</a></p> @jandersonfc usando o restrict mode
  • 15. 3 - Directiva com template externo e Dicas e Truques • Evite usar template externo desnecessário. O angular para usar esse template externo faz uma chamada http (GET). Isso é bem mais lento que deixar o template inline. • Template externo é bem mais legível, eu sei. Uma possibilidade é usar o templateCache. Assim você evitará múltiplas chamadas http desnecessários. Para saber mais sobre templateCache acesse https://docs.angularjs.org/api/ng/service/$templateCache . • Não existe uma regra para usar o restrict mode, é comum achar uma directiva com acesso 'use e abuse' (restrict: ‘EAC’). • É recomendável usar o restrict como Atributo ( restrict: 'A' ) quando sua directiva adicionar ou mudar o comportamento de um componente existente. (ex. <input validar-cpf />). • Quando sua directiva é um novo componente que adicionará novos elementos e comportamentos, recomenda-se usar Element ( restrict: ‘E' ). (ex. <card-profile /> ). @jandersonfc usando o restrict mode
  • 16. 4 - Criando um módulo para a directiva jfc-card-profile.js card-profile04.html View04.html @jandersonfc
  • 17. 4 - Criando um módulo para a directiva Basta adicionar o módulo para ter acesso as directivas. 'use strict'; app.js // Declare app level module which depends on views, and components angular.module('myApp', [ 'ngRoute', 'myApp.view01', 'myApp.view02', 'myApp.view03', 'myApp.view04', 'myApp.view05', 'myApp.view06', 'myApp.view07', 'myApp.view08', 'myApp.view09', 'myApp.view10', 'myApp.version', 'jfc' ]) index.html <!-- In production use: <script src="//ajax.googleapis.com/ajax/libs/angularjs/x.x.x/angular.min.js"></script> --> <script src="bower_components/angular/angular.js"></script> <script src="bower_components/angular-route/angular-route.js"></script> <script src="app.js"></script> <script src="view01/view01.js"></script> <script src="view02/view02.js"></script> <script src="view03/view03.js"></script> <script src="view04/view04.js"></script> <script src="view05/view05.js"></script> <script src="view06/view06.js"></script> <script src="view07/view07.js"></script> <script src="view08/view08.js"></script> <script src="view09/view09.js"></script> <script src="view10/view10.js"></script> <script src="components/jfc-card-profile/jfc-card-profile.js"></script> <script src="components/version/version.js"></script> <script src="components/version/version-directive.js"></script> <script src="components/version/interpolate-filter.js"></script> @jandersonfc
  • 18. 4 - Criando um módulo para a directiva Basta adicionar o módulo para ter acesso as directivas. View04.html <p>This is the partial for view 4.</p> <p>criando um module para a directive para ser usado e N modules</p> <jfc-card-profile04></jfc-card-profile04> card-profile04.html.html <div ng-repeat="user in users"> <h2>{{user.name}}</h2> <p>Twitter: {{user.twitter}}</p> <p>website: <a href="{{user.website}}">{{user.website}}</a></p> </div> @jandersonfc
  • 19. 4 - Criando um módulo para a directiva Dicas e Truques • O Angular espera que o nome de sua directiva seja único. Caso você tenha duas directivas com o mesmo nome, mesmo sendo de módulos distintos, será lançado um erro. • É recomendável usar um identificador inicial em suas directivas (de 2 ou 3 caracteres) para evitar conflitos com outras directivas. (ex. jfcCardProfile ou brCardProfile no lugar de cardProfile). • Não é recomendável usar o identificador inicial ng , esse é o identificador usado nas directivas do próprio Angular. @jandersonfc
  • 20. 5 - Outra view usando a mesma directiva jfc-card-profile.js card-profile04.html View05.html @jandersonfc
  • 21. 6 - Isolando o escopo da directiva jfc-card-profile.js card-profile04.html View06.html @jandersonfc
  • 22. 6 - Isolando o escopo da directiva scope: {} indica que essa directiva terá seu próprio escopo. A directiva não terá mais acesso ao escopo do parent. Nossa directiva só terá acesso as variáveis de escopo informados em sua definição. jfc-card-profile.js .directive('jfcCardProfile06', [function(){ return { restrict: 'E', replace: true, templateUrl: 'components/jfc-card-profile/jfc-card-profile04.html', scope: { users: '=datas' } }; }]) View06.html <p>This is the partial for view 6.</p> <p>Isolando o Scope da Directive</p> <button ng-click="updateUsers()">Update Users</button> <jfc-card-profile06 datas="users"></jfc-card-profile06> @jandersonfc
  • 23. 6 - Isolando o escopo da directiva Se o nome do atributo preenchido no template for igual a variável de escopo que criamos em nossa directiva, podemos usar apenas o símbolo ‘='. jfc-card-profile.js .directive('jfcCardProfile06', [function(){ return { restrict: 'E', replace: true, templateUrl: 'components/jfc-card-profile/jfc-card-profile04.html', scope: { users: '=' } }; }]) View06.html <p>This is the partial for view 6.</p> <p>Isolando o Scope da Directive</p> <button ng-click="updateUsers()">Update Users</button> <jfc-card-profile06 users="users"></jfc-card-profile06> @jandersonfc
  • 24. 6 - Isolando o escopo da directiva O valor '=' indica para a directiva um bi-direcional binding com o escopo do parent, ou seja, mudando o valor dessa variável na directiva mudará também no escopo externo(parent) e vice versa. .directive('jfcCardProfile06', [function(){ return { restrict: 'E', replace: true, templateUrl: 'components/jfc-card-profile/jfc-card-profile04.html', scope: { users: '=' } }; }]) jfc-card-profile.js @jandersonfc
  • 25. 6 - Isolando o escopo da directiva replace: true Vai substituir o elemento raiz da declaração da directiva e vai usar apenas os elementos da directiva. .directive('jfcCardProfile06', [function(){ return { restrict: 'E', replace: true, templateUrl: 'components/jfc-card-profile/jfc-card-profile04.html', scope: { users: '=' } }; }]) jfc-card-profile.js @jandersonfc
  • 26. 6 - Isolando o escopo da directiva replace: false <jfc-card-profile06 datas="users" class="ng-scope ng-isolate-scope”> <!-- ngRepeat: user in users —> <div ng-repeat="user in users" class="ng-scope"> <h2 class="ng-binding">Janderson Fernandes Cardoso</h2> <p class="ng-binding">Twitter: @jandersonfc</p> <p>website: <a href="http://jandersonfc.com" class="ng-binding">http://jandersonfc.com</a></p> replace: true </div><!-- end ngRepeat: user in users —> <div ng-repeat="user in users" class="ng-scope"> <h2 class="ng-binding">Janderson Futebol Clube</h2> <p class="ng-binding">Twitter: @jandersonfclube</p> <p>website: <a href="http://jandersonfclube.com" class="ng-binding">http://jandersonfclube.com</a></p> </div><!-- end ngRepeat: user in users —> </jfc-card-profile06> <!-- ngRepeat: user in users —> <div ng-repeat="user in users" class="ng-scope"> <h2 class="ng-binding">Janderson Fernandes Cardoso</h2> <p class="ng-binding">Twitter: @jandersonfc</p> <p>website: <a href="http://jandersonfc.com" class="ng-binding">http://jandersonfc.com</a></p> </div><!-- end ngRepeat: user in users —> <div ng-repeat="user in users" class="ng-scope"> <h2 class="ng-binding">Janderson Futebol Clube</h2> <p class="ng-binding">Twitter: @jandersonfclube</p> <p>website: <a href="http://jandersonfclube.com" class="ng-binding">http://jandersonfclube.com</a></p> </div><!-- end ngRepeat: user in users —> @jandersonfc
  • 27. 6 - Isolando o escopo da directiva Por que separar o nosso escopo? • Em nosso exemplo, era obrigatório ter uma variável chamada users no escopo do parent para a directiva funcionar. Separando o escopo e passando a informação por atributo resolvemos esse problema. • Isolar o escopo da directiva é o primeiro passo para criar directivas com reuso. • Separando o escopo garantimos que a directiva só tenha acesso as informações cruciais para seu funcionamento, sem correr o risco de alterar algo no escopo do parent acidentalmente. @jandersonfc
  • 28. 7 - Utilizando o Transclude jfc-card-profile.js card-profile07.html View07.html @jandersonfc
  • 29. 7 - Utilizando o Transclude transclude: true indica que a directiva irá extrair os elementos adicionados como "filhos" na declaração da directiva. Transclude é mais que isso, mas para facilitar a compreensão desses exemplos vamos no reter a essa explicação. <jfc-card-profile07 data="user"> <p>linkedin: <a href="{{user.linkedin}}">{{user.linkedin}}</a></p> <p>facebook: <a href="{{user.facebook}}">{{user.facebook}}</a></p> </jfc-card-profile07> View07.html .directive('jfcCardProfile07', [function(){ return { restrict: 'E', replace: true, transclude: true, templateUrl: 'components/jfc-card-profile/jfc-card-profile07.html', scope: { user: '=data' } }; }]) jfc-card-profile.js @jandersonfc
  • 30. 7 - Utilizando o Transclude <div> <h2>{{user.name}}</h2> <p>Twitter: {{user.twitter}}</p> <div ng-transclude></div> <p>website: <a href="{{user.website}}">{{user.website}}</a></p> </div> ng-transclude indica exatamente a posição onde os elementos que foram extraídos serão adicionados. jfc-card-profile07.html @jandersonfc
  • 31. 8 - Adicionando ações a directiva jfc-card-profile.js card-profile08.html @jandersonfc
  • 32. 8 - Adicionando ações a directiva view8.js view08.html @jandersonfc
  • 33. 8 - Adicionando ações a directiva É na função link que criaremos nossas variáveis, funções e manipulação de DOM necessários jfc-card-profile.js link: function(scope, element, attrs) { scope.edit = function(user){ user.editMode = true; } scope.save = function(user){ user.editMode = false; scope.onSave({user: user}); } } <div ng-repeat="user in users"> <p> <h2 ng-hide="user.editMode">{{user.name}}</h2> <input ng-show="user.editMode" ng-model="user.name"/> </p> <p> <span ng-hide="user.editMode">Twitter: {{user.twitter}}</span> <input ng-show="user.editMode" ng-model="user.twitter"/> </p> <p> <span ng-hide="user.editMode">website: <a href="{{user.website}}">{{user.website}}</a></span> <input ng-show="user.editMode" ng-model="user.website"/> </p> <button ng-hide="user.editMode" ng-click=" edit(user)">Edit</button> <button ng-show="user.editMode" ng-click=" save(user)">Save</button> </div> jfc-card-profile08.html @jandersonfc
  • 34. 8 - Adicionando ações a directiva link: function(scope, element, attrs) { • scope - Equivalente ao $scope das controladoras, objeto que contém nossas variáveis e funções acessíveis ao template. • element - Representa o jqlite-wrapped do elemento html da nossa directiva, não é necessário usar o $ do jQuery para manipular esse elemento, o angular já traz ele pronto para isso. É muito comum manipular esse elemento quando a directiva é uma forma de usar um plugin jQuery, ou quando queremos adicionar event listeners nesse elemento. (ex. element.datepicker(), element.on('mousedown', function(event) ) • attrs - traz a lista de atributos e seus valores adicionados na nossa directiva. (ex. <input my-directive min="23" max=“24” />) @jandersonfc
  • 35. 8 - Adicionando ações a directiva Escopo com ‘&’ indica uma expressão, no nosso caso passamos uma função que servirá de callback, veja abaixo: jfc-card-profile.js .directive('jfcCardProfile08', [function(){ return { restrict: 'E', replace: true, transclude: true, templateUrl: 'components/jfc-card-profile/jfc-card- profile08.html', scope: { users: '=datas', onSave: '&' }, link: function(scope, element, attrs) { scope.edit = function(user){ user.editMode = true; } scope.save = function(user){ user.editMode = false; scope.onSave({user: user}); } } }; }]) view08.html <jfc-card-profile08 datas="users" on-save=“saveUser(user)"> </jfc-card-profile08> view08.js .controller('View08Ctrl', ['$scope', function($scope) { $scope.users = [ { name: 'Janderson Fernandes Cardoso', twitter: '@jandersonfc', website: 'http://jandersonfc.com' }, { name: 'Janderson Futebol Clube', twitter: '@jandersonfclube', website: 'http://jandersonfclube.com' } ]; $scope.saveUser = function (user){ console.log('call resource for example'); console.log(user); } }]); @jandersonfc
  • 36. 8 - Adicionando ações a directiva Dicas e Truques • Existe a função compile na directiva. na execução do compile existe a chamada para as funções preLink e postLink. • A função link é equivalente ao postLink do compile. • Ao usar o compile não utilizar a função link. • Não é recomendável usar a função compile, somente em caso de performance onde será necessário executar alguma rotina antes do postLink. @jandersonfc
  • 37. 9 - Criando uma controladora para a directiva jfc-card-profile.js @jandersonfc
  • 38. 9 - Criando uma controladora para a Quando criamos uma controller , ela é instanciada antes da execução da funçao preLink em compile. controller: function($scope) { $scope.setEditModeToFalse = function(){ for (var i = 0; i < $scope.users.length; i++) { $scope.users[i].editMode = false; }; } $scope.edit = function(user){ user.editMode = true; } $scope.save = function(user){ user.editMode = false; $scope.onSave({user: user}); } }, link: function(scope, element, attrs) { scope.setEditModeToFalse(); } jfc-card-profile.js @jandersonfc directiva
  • 39. 9 - Criando uma controladora para a Dicas e Truques • Usar Controladora parece ser uma ótima forma de organizar o código da directiva, deixando a lógica de manipulação de scope na controller e manipulação de DOM na função link . • Na documentação do Angular só é recomendado usar controladora quando você quer expor a API de sua directiva para outras directivas (veremos como isso funciona no exemplo 10). • Portanto, no exemplo 09, não é recomendável usar a função controller, nesse caso é melhor fazer diretamente na função link como no exemplo 08. @jandersonfc directiva
  • 40. 10 - Complicando a vida e criando directivas com dependência de outras directivas view10.html jfc-card-profile.js jfc-card-profile10-list.html @jandersonfc
  • 41. 10 - Complicando a vida e criando directivas com dependência de outras directivas jfc-card-profile10-renderer.html jfc-card-profile.js @jandersonfc
  • 42. 10 - Complicando a vida e criando directivas com dependência de outras directivas jfc-card-profile.js jfc-card-profile10-view.html @jandersonfc
  • 43. 10 - Complicando a vida e criando directivas com dependência de outras directivas jfc-card-profile.js jfc-card-profile10-edit.html @jandersonfc
  • 44. 10 - Complicando a vida e criando directivas com dependência de outras directivas Podemos criar directivas que possuem outras directivas jfc-card-profile10-list.html <jfc-card-profile10-renderer ng-repeat="user in users" ng-switch on="user.mode"> </jfc-card-profile10-renderer> @jandersonfc
  • 45. 10 - Complicando a vida e criando directivas com dependência de outras directivas A controladora pode ser declarada diretamente na directivas como fizemos no exemplo 09 ou referenciar uma controller existente no módulo. .controller('cardProfileController', ['$scope', '$attrs', function($scope, $attrs){ this.setModeDefault = function(){ $scope.user.mode = 'view'; } this.edit = function(){ $scope.user.mode = 'edit'; } this.save = function(){ $scope.user.mode = 'view'; $scope.onSave({user: $scope.user}); } }]) .directive('jfcCardProfile10Renderer', function(){ return { restrict: 'E', replace: false, controller: 'cardProfileController', templateUrl: 'components/jfc-card-profile/jfc-card-profile10-renderer.html', link: function(scope, element, attrs, ctrl) { ctrl.setModeDefault(); } }; }) jfc-card-profile.js @jandersonfc
  • 46. 10 - Complicando a vida e criando directivas com dependência de outras directivas A controladora da directiva pode ser acessada através do quarto parâmetro na declaração da função link. .controller('cardProfileController', ['$scope', '$attrs', function($scope, $attrs){ this.setModeDefault = function(){ $scope.user.mode = 'view'; } this.edit = function(){ $scope.user.mode = 'edit'; } this.save = function(){ $scope.user.mode = 'view'; $scope.onSave({user: $scope.user}); } }]) .directive('jfcCardProfile10Renderer', function(){ return { restrict: 'E', replace: false, controller: 'cardProfileController', templateUrl: 'components/jfc-card-profile/jfc-card-profile10-renderer.html', link: function(scope, element, attrs, ctrl) { ctrl.setModeDefault(); } }; }) jfc-card-profile.js @jandersonfc
  • 47. 10 - Complicando a vida e criando directivas com dependência de outras directivas ng-switch é uma diretiva do angular que você pode usar para facilitar a troca de estrutura de DOM. jfc-card-profile10-list.html <jfc-card-profile10-renderer ng-repeat="user in users" ng-switch on="user.mode"> </jfc-card-profile10-renderer> jfc-card-profile10-renderer.html <jfc-card-profile10-view ng-switch-when="view"></jfc-card-profile10-view> <jfc-card-profile10-edit ng-switch-when="edit"></jfc-card-profile10-edit> @jandersonfc
  • 48. 10 - Complicando a vida e criando directivas com dependência de outras directivas Nossa directiva Renderer adiciona mais duas directivas em nosso projeto. View e Edit. jfc-card-profile10-renderer.html <jfc-card-profile10-view ng-switch-when="view"></jfc-card-profile10-view> <jfc-card-profile10-edit ng-switch-when="edit"></jfc-card-profile10-edit> @jandersonfc
  • 49. 10 - Complicando a vida e criando directivas com dependência de outras directivas Nossa directiva View compartilha da mesma controladora que a Renderer. para isso usamos o atributo require. O símbolo ^ indica que é obrigatório que jfcCardProfile10Renderer seja declarada em um parent element e que a mesma possua uma controladora. Existem outros símbolos que podem ser passados no require ( ?, ^^, ?^, ?^^ ). Olhe a documentação para mais detalhes. jfc-card-profile10.js .directive('jfcCardProfile10View', function(){ return { restrict: 'E', replace: true, templateUrl: 'components/jfc-card-profile/jfc-card-profile10-view.html', require: '^jfcCardProfile10Renderer', link: function(scope, element, attrs, ctrl) { scope.edit = function(){ ctrl.edit(); } } }; }) @jandersonfc
  • 50. 10 - Complicando a vida e criando directivas com dependência de outras directivas Agora que nossa directiva View compartilha da mesma controller da Renderer. Podemos acessar nossa controladora através do quarto parâmetro. jfc-card-profile10.js .directive('jfcCardProfile10View', function(){ return { restrict: 'E', replace: true, templateUrl: 'components/jfc-card-profile/jfc-card-profile10-view.html', require: '^jfcCardProfile10Renderer', link: function(scope, element, attrs, ctrl) { scope.edit = function(){ ctrl.edit(); } } }; }) @jandersonfc
  • 51. 10 - Complicando a vida e criando directivas com dependência de outras directivas O mesmo acontece com nossa diretiva Edit. jfc-card-profile10.js .directive('jfcCardProfile10Edit', function(){ return { restrict: 'E', replace: true, templateUrl: 'components/jfc-card-profile/jfc-card-profile10-edit.html', require: '^jfcCardProfile10Renderer', link: function(scope, element, attrs, ctrl) { scope.save = function(){ ctrl.save(); } } }; }); @jandersonfc
  • 52. E agora? • Pense 2 vezes antes de criar um directiva. Evite criar directivas desnecessárias. • Directiva é sempre muito útil, mas isso não significa que a forma como é criada hoje seja prática. Por isso, evite criar directivas desnecessárias. • No AngularJS 2 terá uma grande mudança na forma de criar directivas, e isso é muito bom! então evite criar directivas desnecessárias. • Polymer é outro projeto do Google que trabalha já com os Web Components. Não tenho dúvida que web components é a melhor forma de criar componentes. Polymer terá integração garantida no AngulaJS 2. Por favor, evite criar directivas desnecessárias. • Essa apresentação e todo o material de apoio foi criado se baseando unicamente na excelente documentação do AngularJS ( https://docs.angularjs.org/guide/directive ). Mesmo assim, evite criar directivas desnecessárias. :P • O material de apoio dessa apresentação pode ser acessada em https://github.com/jandersonfc/tutorial-angularjs-directives @jandersonfc