Arquivo da tag: diretiva

AngularJS – Diretivas

pic_angularOlá pessoal. Dando continuidade ao meu estudo sobre o angular, deixo aqui registrado o que estudei e entendi sobre diretivas.

Diretivas dão poder ao programador para estender/ampliar o comportamento de elementos HTML, e é responsável pela manipulação do DOM. Uma diretiva é capaz de selecionar um elemento HTML por seu atributo (associado ao nome da diretiva), ou nome do elemento, ou por um comentário, ou mesmo pelo valor do atributo class.

Ao selecionar um elemento HTML, a diretiva pode ampliar seu comportamento, adicionando um novo HTML, manipulando o DOM, ou ainda associando eventos à funções Javascript.

São diversas as diretivas nativas do angular: ng-controller, ng-model, ng-repeat, ng-show, ng-hide, ng-click, ng-blur, ng-change, ng-checked, ng-focus, ng-keydown, ng-keypress, ng-keyup, e diversas outras.

Podemos criar nossas próprias diretivas (Custom Directives), para por exemplo:

    • Criar componentes como: abas, janelas de mensagens, janelas pop-up, calendário, etc…;
    • Intercecptar a vinculação de dados e tratá-los se necessário;
    • Criar uma esquema padronizado para validação do model;
    • Tratar eventos dos elementos HTML;
    • Etc…

Uma diretiva customizada deve estar associada a um módulo, podendo ser o próprio módulo da página:

<body ng-app="myApp">
    <div minha-diretiva></div>
</body>
var app = angular.module('myApp', []);

app.directive('minhaDiretiva', function () {
   return {
	restrict: 'A',
	link: function (scope, elem, attrs) {
		elem[0].innerHTML = "minha diretiva....";
	}
   }
});

No exemplo acima, a função directive() do módulo, é usada para criar uma diretiva chamada “minhaDiretiva”, retornando um objeto literal com suas definições. A propriedade restrict é usada para especificar como a diretiva irá selecionar o elemento HTML. Os valores válidos para restrict são:

  • ‘A’ – Atributo:
  • ‘E’ – Elemento:
  • ‘C’ – Class:
  • ‘M’ – Comentário:

A propriedade link deve ser associada a uma função de ligação que faz o trabalho de definição da diretiva. Parâmetros da função: scope, elem e attrs.

  • scope: dá acesso ao escopo da diretiva;
  • elem: é um objeto JQuery Lite contendo o elemento encontrado pela diretiva;
  • attrs: é um objeto que mantém todas as propriedades do objeto encontrado pela diretiva.

O resultado final após a execução da diretiva é:

<div minha-diretiva="">minha diretiva....</div>

Agora vou alterar a diretiva anterior para localizar elementos HTML pelo nome (customizado) da tag do elemento. Com angular, posso criar meus tipos de elemento HTML e definir seu comportamento.

<body ng-app="myApp">
    <minha-diretiva></minha-diretiva>
</body>
var app = angular.module('myApp', []);

app.directive('minhaDiretiva', function () {
   return {
	restrict: 'E',
	link: function (scope, elem, attrs) {
		elem[0].innerHTML = "minha diretiva....";
	}
   }
});

O resultado final é:

<minha-diretiva>minha diretiva....</minha-diretiva>

Observação: é padrão no angular o nome da diretiva seguir a nomenclatura: “primeira palavra iniciando em minusculo e demais com inicial maiúscula”, por exemplo: minhaDiretiva, janelaMensagem, etc. No momento de usar (no HTML) fica assim (dash-delimited): minha-diretiva, janela-mensagem, etc.

Utilizando o conceito de diretivas, também é possível criar templates utilizando as propriedades template ou templateUrl do objeto de retorno de definição da diretiva.

Avançando um pouco mais, mas nem tanto. Uma diretiva também pode ser um template. Observe:

<span meu-template="meu primeio template...">
app.directive('meuTemplate', function () {

    return {

        restrict: 'A',
        scope: {},
        link: function (scope, elem, attrs) {
            scope.msg = attrs.meuTemplate;
        },
        template: '<div><strong>{{msg}}</strong></div>',
        replace: false
    }
});

Ao usar a diretiva acima, obtém-se o seguinte resultado após a renderização:

<span meu-template="meu primeio template...">
    <div>
	 <strong>meu primeio template...</strong>
   </div>
</span>

O conteúdo da propriedade template da diretiva foi incluído dentro do elemento span selecionado pela diretiva. Isso ocorreu devido a propriedade replace estar configurada como false. Se configurado com true, o elemento span é totalmente substituído pelo conteúdo do template, observe o resultado da renderização:

<div meu-template="meu primeio template...">
   <strong>meu primeio template...</strong>
</div>

Há também no objeto de definição da diretiva para elementos (restrict: ‘E’) uma propriedade chamada transclude, que é capaz e anexar/incluir elementos (do contêiner selecionado pela diretiva) dentro do template da diretiva.

E para finalizar, segue um exemplo (simplório) de diretiva para mostrar áreas de mensagens.

app.directive('msgAlert', function () {

    return {
        restrict: 'A',
        scope: { textoMsg: '@'},
               
        template: '<div class="msgAlert">{{textoMsg}} <input type="button" value="(fechar)" ng-click="esconder()" /></div>',
        replace: true,
               
        link: function (scope, elemento, attrs) {
            scope.esconder = function () {
                scope.$parent.mostrarAlert = false;
            }
        }
    };
});

<style>
    .msgAlert {
        background-color:#ffd800;
        border: 1px solid #808080;
        padding: 5px;
        margin: 5px;  
   }
</style>

<div msg-alert texto-msg="{{msg}}" ng-show="mostrarAlert"></div>
<input type="button" value="mostrar alerta" ng-click="abrirAlert()" />

Conclui que usar diretivas não é tão fácil. :-(