- Cómo crear una directiva personalizada en AngularJS
- Directivas angular para manejar el HTML
- Las directivas de Angular: Manejar expresiones
- Las directivas de Angular: Introducción y cómo usarlas
Hasta ahora hemos visto cómo usar las directivas que nos ofrece AngularJS pero, es muy probable que en más de una ocasión nos sepan a poco y precisemos algo mucho más específico. Para ello voy a mostrar cómo crear vuestra directiva personalizada en AngularJS.
La idea de este post es dar unas bases para poder afrontar conceptos más avanzados en cuánto directivas. Para conseguir este objetivo, vamos a crear una directivas llamada arcoiris. Esta directiva va encapsular una buena parte del código que hemos visto anteriormente. Lo que queremos hacer con está directiva es mostrar el arcoiris en función de pulsar un botón.
Antes de comenzar a crear nuestra directiva personalizada en AngularJS, es preciso que esté configurada en un módulo. Creamos un archivo js llamado arcoiris donde iremos abordando cada paso en la creación de la directiva.
Comenzamos declarando el módulo llamado moduloArcoiris. Lo asignamos dentro de una variable para que seas más fácil emplearlo más adelante.
1 |
var moduloArcoiris = angular.module('moduloArcoiris', []); |
A continuación procedemos con la declaración directiva. Tendrá más contenido pero de momento esto nos servirá para aclarar ciertos conceptos
1 2 3 4 5 6 7 8 9 10 11 12 |
moduloArcoiris.directive('arcoiris', function () { return { restrict: 'AE', template: "<button ng-click='mostarArcoiris()' type='button'>" + "{{oculto ? 'Dejar de llover' : 'Que llueva'}}" + "</button><div ng-hide='oculto' id='colorContainer'>" + "</div>", }; }); |
Al emplear el método directive, estamos registrando nuestra directiva al framework de AngularJS. Dicho método tiene 2 parámetros, 1º el nombre de la directiva (arcoiris) y el 2º es una función anónima que devuelve la directiva. Pero que son las opciones restrict y template?
La opción restrict
Con esta opción indicamos cómo puede ser invocada una directiva personalizada en AngularJS. Si remontamos un post atrás, había 4 maneras de invocar una directiva. Esto corresponde a las 4 opciones válidas para restrict.
Opción | Definición | Ejemplo |
---|---|---|
A | Invoca la directiva como un atributo | «<span arcoiris ></span>» |
E | Se puede invocar mediante etiquetas | «<arcoiris ></arcoiris >» |
C | Invocación a través de una clase | «<span class=»arcoiris «></span>» |
M | Cómo un comentario | «<!– directive: arcoiris –>» |
En nuestra directiva hemos especificado AE, esto quiere decir que podemos invocar tanto cómo un atributo como un elemento. Las otras 2 opciones (C y M) están pensados para navegadores muy viejos.
En lo referido a cómo usarlo, que se recomienda más? Al final usarlo como atributo o elemento no va a influir en el resultado. Sin embargo, el equipo de Angular recomienda que usemos la directiva como un elemento si vamos a crear un componente que está dentro de la plantilla y un atributo cuando vayamos a decorar un elemento existente con nueva funcionalidad.
La opción template
Se establece el código HTML o plantilla de nuestra directiva personalizada en AngularJS. Esta plantilla se va a agregar justo después del lugar donde declaraste la directiva (aunque existe la opción replace si queremos que se remplace el elemento donde la directiva es invocada). Este seería el código que va a introducirse sino fueran strings.
1 2 3 4 5 |
<button ng-click='mostarArcoiris()' type='button'> {{oculto ? 'Dejar de llover' : 'Que llueva'}} </button> <div ng-hide='oculto' id='colorContainer'></div> |
Este código ya estaba presente en el ejemplo anterior. Básicamente consiste en un botón que invocará a la función que mostrará el arcoiris. Dicha función hará que el div que contiene los colores se oculte o muestre.
Como puedes observar, empleamos directivas como ng-click y ng-hide dentro de la directiva. Esto es un ejemplo que una plantilla puede ser tan simple o compleja como lo necesites.
Ahora con estas 2 opciones explicadas, pasamos a la siguiente opción, link.
La opción link
La función que agreguemos a esta opción será la que realice la tarea principal de nuestra directiva personalizada en AngularJS. Esta función tiene acceso al objeto scope y al elemento donde la directiva ha sido declarada. Necesitamos que la función en link muestre u oculte el arcoiris y manipule el DOM para agregar los colores al colorContainer.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
link: function ($scope, $element) { //Ocultamos los colores por defecto $scope.oculto = true; //Creamos una funcion dentro del objeto scope y será invocado cuando cliquemos el boton //La función lo que hacer es invertir el valor de la variable oculto $scope.mostarArcoiris = function () { $scope.oculto = !$scope.oculto; } // DOM manipulation var colorContainer = $element.find('div'); angular.forEach($scope.$parent.coloresArcoiris, function (color) { var appendString = "<div style='background-color:" + color + "'>" + color + "</div>"; colorContainer.append(appendString); }); } |
Como vemos en la función link, tenemos acceso al elemento donde la directiva es llamda ($element) y al objeto scope. Los argumentos de está función son automáticamente inyectados a nuestra función por el framework de manera que sólo tenemos que preocuparnos de escribir estos 2 argumentos.
Dentro de la función observamos que la funcionalidad es exactamente igual que el caso anterior. Declaramos el valor de oculto por defecto y la funión que hace que alterne su valor entre true y false. La novedad es que ahora manipulamos el DOM que es el meollo principal de la directiva.
Como queremos crear los elementos dinámicamente dentro del div colorContainer, creamos la variable colorContainer
1 |
var colorContainer = $element.find('div'); |
Si estas familiarizado con jQuery es probable que esto te resulte familiar. Lo que hacemos es seleccionar el div(creado en la option template) que está del elemento donde se ha llamado la directiva y lo metemos en la variable colorContainer para facilitar su manejo.
Una vez que tenemos la referencia de colorContainer, vamos a añadir dentro del div los div con sus respectivos colores. Dichos colores están dentro de un array (que comentaré más tarde) y para recorrerlo empleamos un bucle foreach. Dicho bucle se llama con el método .forEach() donde indicamos que array se va a recorrer y una función anónima que indica sus acciones, teniendo como parámetro la referencia del elemento que estemos recorriendo en el array (como cuando usamos as en un bucle foreach de PHP).
Declarar el controlador y crear el array coloresArcoiris
El array coloresArcoiris lo declaramos dentro del controlador. Justo después de declarar el módulo (y antes de la directiva), creamos un controlador con los colores dentro del array.
1 2 3 4 5 6 7 8 |
var moduloArcoiris = angular.module('moduloArcoiris', []); moduloArcoiris.controller('miControlador', function ($scope) { $scope.coloresArcoiris = ['#9400D3', '#4B0082', '#0000FF', '#00FF00', '#FFFF00', '#FF7F00', '#FF0000'] } ); moduloArcoiris.directive('arcoiris', function () { |
Dicho array lo declaro en el controlador para mostrar el uso de $scope en la directiva. Crear el array dentro de la option link es completamente válido.
Resultado final
Ahora podemos emplear la directiva arcoiris sin ningún problema. El resultado final sería el siguiente
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
<!DOCTYPE html > <html ng-app="moduloArcoiris"> <meta charset="UTF-8"> <title></title> <script src="angular.min.js"></script> <script src="arcoiris.js"></script> <style> div{ margin: 20px; padding: 20px; font-size: 16px; color:#ffffff; } .arco{ width:500px; height:20px; } </style> </head> <body ng-controller="miControlador"> <h2>Arcoiris AngularJS</h2> <p>Haz que pare de llover para ver el arcoiris</p> <div arcoiris colors="coloresArcoiris"></div> </body> </html> |
Nuestro script arcoiris.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
// Creacion del modulo var moduloArcoiris = angular.module('moduloArcoiris', []); moduloArcoiris.controller('miControlador', function ($scope) { $scope.coloresArcoiris = ['#9400D3', '#4B0082', '#0000FF', '#00FF00', '#FFFF00', '#FF7F00', '#FF0000'] } ); //Configurar el modulo con un controlador moduloArcoiris.directive('arcoiris', function () { return { restrict: 'AE', template: "<button ng-click='mostarArcoiris()' type='button'>" + "{{oculto ? 'Dejar de llover' : 'Que llueva'}}" + "</button><div ng-hide='oculto' id='colorContainer'>" + "</div>", link: function ($scope, $element) { //Ocultamos los colores por defecto $scope.oculto = true; //Creamos una funcion dentro del objeto scope y será invocado cuando cliquemos el boton //La funcioçon lo que hacer es invertir el valor de la variable oculto $scope.mostarArcoiris = function () { $scope.oculto = !$scope.oculto; } // DOM manipulation var colorContainer = $element.find('div'); angular.forEach($scope.coloresArcoiris, function (color) { var appendString = "<div class='arco' style='background-color:" + color + "'>" + color + "</div>"; colorContainer.append(appendString); }); } }; }); |
Y hasta aquí cómo crear una directiva personalizada en AngularJS, espero que os haya gustado. A seguir picando 🙂