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





viernes, 22 de septiembre de 2017

[JavaScript] Usar checkbox en Kendo Grid con valores booleanos

Introducción

El grid de KendoUI soporta datos del tipo booleano, pero su funcionalidad de edición para el usuario se representa en forma de un campo "select" (DropDown) con las opciones de "verdadero" y "falso". De forma nativa no permite poner un "CheckBox" que realice esta función y si se quiere hacer uso del template para poner el "CheckBox" éste no actualiza por sí solo la información del campo en el grid.
Para términos de la explicación

En los ejemplos de esta explicación se tiene el siguiente ambiente:

  • Un grid con ID: "div-monitor-data-grid"
  • El grid tiene como "DataSource" un arreglo llamado "resultadoFlujo".
  • Los objetos del DataSource tienen un atributo llamado "Seleccionada", el cual es el "booleano" que se quiere manipular con el checkbox; éste deberá ser sustituido por el atributo que se desea manipular en sus propios casos.
  • Los objetos del DataSource tienen un atributo que les sirve de llave primaria: IdDetalle; éste deberá ser reemplazado por el o los atributos que identifiquen de manera única los objetos en sus propios casos.

Solución

Debido a que la única forma (Hasta ahora conocida) de agregar un campo tipo CheckBox a un GRID en kendo es mediante del Template se hará uso de éste, poniendo una condición para que cuando el campo tenga el valor "true" el input esté seleccionado y deseleccionado para el caso contrario:

{
    title: "Seleccionar",
    field: "Seleccionada",
    template: "#if(Seleccionada){#<div class='text-center'><input  type='checkbox'  class='chkSeleccionada' checked/></div>#}else{#<div class='text-center'><input  type='checkbox'  class='chkSeleccionada'/></div>#}#",
},

Como se aprecia, el checkbox contiene una clase (En este caso: "chkSeleccionada"), la cual servirá para capturar el evento de éste al ser "clickeado" por el usuario; ésta función se "amarrará" al grid donde se encuentre el input, además de que se realizará en una función "anónima" para que se ejecute en cada momento:

$(function () {
  $('#id-del-grid').on('click', '.chkSeleccionada', function () { //Como se ve, el evento se da a la clase "chkSeleccionada"
    .......
  });
});

La lógica dentro del evento debe ser la siguiente:
Obtener el valor del checkbox (Si está o no seleccionado).
Recuperar el objeto del grid del cual obtendremos el objeto de la tupla que corresponde al checkbox clickeado.
Recorremos la lista que funge de "DataSource" para el "Grid". En cada iteración se compara con el objeto de la tupla seleccionada; y de ser ésta la tupla, al objeto del arreglo se le da el valor del checkbox (True o false).
Se refresca el grid al terminar de iterar.
El código final de ésta función quedaría así:

$(function () {
  $('#div-monitor-data-grid').on('click', '.chkSeleccionada', function () {
     var checked = $(this).is(':checked'); //Se obtiene el valor del checkbox
     var grid = $('#div-monitor-data-grid').data().kendoGrid; //Se obtiene el objeto del grid
     var dataItem = grid.dataItem($(this).closest('tr')); //Se obtiene la tupla que corresponde al checkbox
     for (var i = 0; i < vm.resultadoFlujo.length; i++)
    { //Se itera el datasource
       if (vm.resultadoFlujo[i].IdDetalle == dataItem.IdDetalle)
      { //Se pregunta si es el mismo objeto del checkbox
         vm.resultadoFlujo[i].Seleccionada = checked; //Se edita el valor del atributo por el del checkbox
      }
    }
    grid.dataSource.read(); // Se vuelve a "leer" el dataSource del grid.
    grid.refresh(); //Se refresca el GRID.
  });
});

martes, 3 de enero de 2017

[JavaScript][Jquery] Convertir todas las cadenas de un objeto (O cualquier variable) a mayúsculas

Como anécdota personal, en mi trabajo se hacen llamados a servicios web desde JavaScript enviando objetos con los cuales se interactuará en la base de datos; la norma es que toda cadena que se envía a la base de datos debe de estar formateada a mayúsculas, y es un gran lío pasar atributo por atributo (o campo por campo) a mayúsculas de forma manual.
Ante ésto me di la ligera tarea de crear una función que usando la recursividad, y testeando el tipo de datos con el cual trabaja en cada iteración, recorra todos los elementos del objeto y, cada cadena con la que se interactua es convertida a mayúsculas.
Ahora les comparto tal función para su uso personal, aunque eso sí, se ha de incluir la librería de JQuery al sitio donde trabajan, debido a que se hace uso de su función "type()" para saber con qué tipo de dato se está trabajando.

Les presento el código:



function objectUpperCase(objeto)
{
if(jQuery.type(objeto) == "string")
{
return objeto.toUpperCase();
}
if(jQuery.type( objeto ) == "array")
{
var arreglo = [];
for(var i=0;i<objeto.length;i++)
{
arreglo.push(objectUpperCase(objeto[i]));
}
return arreglo;
}
if(jQuery.type( objeto )=="object" || jQuery.type( objeto )=="function")
{
for (var atributo in objeto) {
objeto[atributo] = objectUpperCase(objeto[atributo]);
}
}
return objeto;
}



Como mencioné anteriormente, se testea el tipo de dato con el que se trabaja y dependiendo de ésto (cadena, array, objeto, función...) se hace uso de la recursividad para interactuar con sus elementos (en caso de que sea un objeto o arreglo), se convierte a mayúsculas (En caso de que sea directamente una cadena) o se ignora en cualquier caso que no requiera interacción. De esta forma se garantiza que aún usando objeto "complejos", todos las cadenas que se manejen serán convertidas a mayúsculas estén en la profundidad que estén.

La única desventaja de este método es la recursividad misma en JavaScript, debido a que los navegadores limitan el uso de memoria así como de llamadas recursivas de forma interna. Lo que nos limita a una profundidad no mayor de 8 o  10 (dependiendo del navegador a utilizar).

[JavaScript] Llenar cadena de ceros (o cualquier caracter) a la izquierda

En ocasiones se requiere formatear a una cadena con una longitud estática, rellenando con un carácter (Comúnmente ceros 0s) a la izquierda las posiciones faltantes; por ejemplo, si se requiere tener una cadena de longitud 6 y se tiene la cadena "123", será necesario convertirla a "000123".

JavaScript no cuenta con una función nativa para "rellenar" una cadena con un carácter específico para que ésta tenga una longitud determinada; y las mayorías de las soluciones a este problema consiste en bucles y condicionales que se extienden más allá de la simpleza del problema. La solución que propongo en esta ocasión consiste en un método que genera una cadena tal que, al concatenarla con el texto que ya se tiene, se obtenga un "String" con la longitud determinada.

La solución sería la siguiente:


caracter.repeat(longitud- String(cadena).length).concat(cadena);



O, expresado a una función:


function llenarCadena(cadena,longitud,caracter)
{
        //Siendo "cadena" el texto a completar
        //"longitud" el largo de la cadena deseada
        //"caracter" el símbolo con el cual se llenarán los espacios faltantes
return caracter.repeat(longitud- String(cadena).length).concat(cadena);
}



La lógica es sencilla; como expliqué arriba, consiste en crear una cadena de caracteres (caracter.repeat) con la longitud necesaria (longitud- String(cadena).length), tal que al concatenarla con la cadena original, nos dé un texto con la longitud deseada.
En pocas palabras, usando el ejemplo inicial; la parte del código "caracter.repeat(longitud- String(cadena).length)" generará la cadena "000" el cual, al concatenarse con la cadena original, dará un texto de longitud 6.

Pues bien, sería todo. Espero les sea de utilidad