Me lo contaron y lo olvidé, lo leí y lo entendí, lo hice y lo aprendí.





viernes, 20 de mayo de 2016

Obtener arreglo desde una lista de "CheckBox" con AngularJs

AngularJs es un Framework de JavaScript de código abierto, mantenido por google. Su existencia es más que una simple curiosidad, ya que permite a desarrolladores crear aplicaciones web de "una sola página" (Single Page Applications). Este framework nos da la facilidad de manipular datos entre el "DOOM" de HTML y las variables en JavaScript sin tener que usar código intermedio para mantener este "puenteo" (binding) que siempre nos ha costado líneas de código adicionales y, sobre todo, extensas en nuestros ficheros de JavaScript.
Aunque, por muy hermoso que sugiere ser la herramienta, siempre existirán casos específicos los cuales tendremos que resolver por nuestra propia cuenta; tal es el caso del tema que abordo en esta publicación y que, seguramente, te habrás topado (o te toparás): querer obtener un arreglo de una lista de "CheckBox", usando AngularJs claro.
Aunque varios programadores han creado sus propias directivas que el framework permite configurar, la propuesta que presento se destaca por su simpleza en el código.

Para esta función me base en tres elementos técnicos:

  1. AngularJs crea (Y elimina) elementos de JavaScript según sea necesario. Aunque no declares un objeto o atributo en el controlador de Angular, si lo utilizas en la vista HTML el framework automáticamente lo creará en cuando el usuario interactue con él.
  2. En un campo de formulario declarado como Requerido (REQUIRED) no existen o se eliminan si éste no contiene un valor (O uno inválido).
  3. La función "$.map" de JQuery que interactúa con varios items y devuelve un arreglo de éstos (En este caso, se interactúa con los atributos de un objeto).

Primero vamos a preparar el archivo HTML de nuestro ejemplo:

<html >
<head>
<meta charset="UTF-8">
<title>Checkbox array list AngularJS</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<script src="controller.js"></script>
</head>
<body>

</body>
</html>

Como ven, importo las librerías de Jquery y Angular (desde las apis de Google). Además de que haré uso de un archivo de JavaScript llamado controller.js el cual tendrá el código de AngularJs.

Justo en el archivo controller.js pondré el siguiente código de prueba:

var app = angular.module('myApp', []);
app.controller('indexController', function($scope) {
        var vm = this;
vm.lista = [
{id:1,valor:"Juanito Alcachofa"},
{id:2,valor:"Padro Alcántara"},
{id:3,valor:"María Mercedez"},
{id:4,valor:"Romero Romerío"},
{id:5,valor:"Susana Nollores"},
];
vm.seleccionados={};
});

Creo la App: "myApp", y en controller: "indexController".
Aquí declaro dos variables que formarán parte del controller:
  • vm.lista: nos servirá para desplegar la lista de los checkbox.
  • vm.seleccionados: Será el objeto donde se "almacenarán" los checkbox seleccionados y que, posteriormente, convertiremos en un arreglo.
Quiero aclarar que para cuestiones de espacio, declaro la variable "vm = this" para hacer referencia al "$scope" de una forma más corta, nada más.

Ahora, volveremos al archivo HTML para desplegar la Interfaz; dentro del "BODY":

<div ng-app="myApp" ng-controller="indexController as vm">
<p ng-repeat="elemento in vm.lista" > 
<input type="checkbox" ng-model="vm.seleccionados[elemento.id]" required/>{{elemento.valor}} 
</p>
<p>{{vm.seleccionados}}</p>
<p><button ng-click="vm.obtenerSeleccionados();">Mostrar arreglo</button></p>
</div>

  • Creo un "DIV" en el cual hago instancia de la app y del controller (A este último le vuelvo a dar un alias: vm, para hacer una referencia corta al controlador).
  • Creo una etiqueta "P" en la cual uso la directiva "ng-repeat" para iterar la lista que declaramos en el controlador "indexController. 
  • Dentro de la etiqueta "P" creo los "checkbox"; note que en la directiva "ng-model" le indico "vm.seleccionados[elemento.id]" lo que quiere decir que al objeto "vm.seleccionados" le estaremos modificando el atributo dado por "elemento.id" el cual, aunque nosotros no lo hayamos declarado, el mismo AngularJs lo irá creando o destruyendo conforme se vaya necesitando.
  • Por último, observe que los "checkbox" tiene el atributo "required", o sea que la variable indicada por "ng-model" (En este caso "vm.seleccionados[elemento.id]") existirá sólo si se marca el imput.
  • Tenemos un párrafo con la directiva {{vm.selccionados}} únicamente con fines de "debugeo" en tiempo real.
  • Finalmente, tenemos un botón que, al ser presionado, llama a la función "obtenerSeleccionados()" la cual declararemos hasta el final.
¿Qué nos da eso como resultado? muy simple, el objeto "vm.seleccionado" se le añadirá el atributo "elemento.id" si y solo si se marca el checkbox correspondiente. Por ejemplo, si están seleccionados los checkbox cuyo Id sean "1,4 y 5" entonces el objeto vm.seleccionados tendrá los atributos: {1:true,4:true,5:true}. Se le asigna el valor "true" debido a que por defecto los "checkbox" trabajan con valores booleanos.

Por último, crearemos la función obtenerSeleccionados() la cual nos regresará el arreglo de con los valores de los "checkbox" seleccionados; la función contendrá lo siguiente:

return $.map(
vm.seleccionados, function (value, index) { if(value){ return [index];}  }
);


Como ven, es una simple línea que regresa el resultado de $.map; a esta función se le pasa como primer parámetro el objeto o arreglo que iterará, en el segundo parámetro se le pasa la función (con dos argumentos de valor e índice que representa cada elemento del objeto) la cual indicará qué nos regresará en cada índice del arreglo resultante, en este caso sólo nos regresará el índice (Que será el Id de cada elemento de la lista). Así pues, el archivo JS termina de la siguiente forma:

"use strict";

var app = angular.module('myApp', []);
app.controller('indexController', function($scope) {
    var vm = this;
vm.lista = [
{id:1,valor:"Juanito Alcachofa"},
{id:2,valor:"Padro Alcántara"},
{id:3,valor:"María Mercedez"},
{id:4,valor:"Romero Romerío"},
{id:5,valor:"Susana Nollores"},
];
vm.seleccionados={};
vm.obtenerSeleccionados = function()
{
return $.map(
vm.seleccionados, function (value, index) {  return [index];  }
);
}
});


El ejemplo funcional sería el siguiente (La función "obtenerSeleccionados" fue modificada para que lanzara un "alert" con el contenido del arreglo resultante):


Y el enlace de descarga directa desde Google Drive

No hay comentarios:

Publicar un comentario