Persistencia de las preferencias de la columna jqGrid

Tengo algunas jqGrids en mi aplicación ASP.NET MVC 3 que tienen varias columnas. Agregué lo siguiente a las definiciones de columna para que algunas columnas se oculten por defecto:

colModel: [ { name: 'IceCreamID', hidden: true}, { name: 'RecipeID', hidden: true } 

y esto funciona muy bien Esas columnas no son visibles en mi grilla.

Luego agregué esto para implementar el selector de columnas:

 var grid = $('#icecreamGrid'); grid.jqGrid('navButtonAdd', '#icecreamPager', { caption: "Columns", buttonicon: "ui-icon-calculator", title: "Choose Columns", onClickButton: function() { grid.jqGrid('columnChooser'); } }); 

Genial, saca el selector de columna ahora. Luego agregué lo siguiente a las columnas que nunca quise mostrar en el selector de columnas:

 colModel: [ { name: 'IceCreamID', hidden: true, hidedlg: true}, 

Así que ahora puedo ocultar / mostrar columnas muy bien. Ahora, ¿cómo persistirías esta información? DB? Como una galleta? ¿Otra manera? ¿Existe una forma preferida de almacenar este tipo de información que sea realmente una preferencia del usuario en lugar de almacenar algo relacionado con los datos en sí?


Más información

Basado en el comentario de Oleg a continuación, quiero brindar un poco más de información.

El punto aquí es que tengo cuadrículas con 10-15 columnas que pueden mostrarse según las preferencias del usuario. Para un ejemplo simple, uno de mis cuadrículas tiene las siguientes 9 columnas:

 IceCream|ShortName|HasNuts|SugarAdded|LimitedRun|PromoItem|Facility|FirstRun|LastRun 

Los usuarios pueden ocultar / mostrar cualquiera de estas 9 columnas en función de sus preferencias personales.

Lo que quiero hacer es proporcionar una forma de persistir en las columnas que un usuario particular quiere ver para que no tenga que volver a elegir esas columnas para verlas cada vez que se muestre la página con esa cuadrícula.

Encontré tu pregunta muy interesante. La pregunta sobre cómo guardar el estado de usuario de la red es interesante en muchos casos. Hay algunas respuestas interesantes sobre tales problemas que usan cookies (ver aquí por ejemplo).

En mi opinión, el ahorro del estado de la cuadrícula en la base de datos en el servidor o en el localStorage es una mejor manera que el uso de cookies. La mejor manera depende de los requisitos del proyecto en el que lo use. Por ejemplo, el uso del almacenamiento de la base de datos en el servidor le permite implementar el estado de itinerancia de la red. Si usa localStorage lugar de cookies, las preferencias del usuario se perderán si el usuario va a otra computadora o si el usuario utilizará otro navegador web en la misma computadora.

Otro problema con el estado de la red es el mantenimiento. La información sobre las columnas de la cuadrícula que tiene normalmente en los archivos JavaScript o HTML y no en la base de datos. En el caso de que ambas fonts puedan no ser sincrónicas en los cambios en la grilla. Diferentes escenarios del problema de actualización podrían imaginarse fácilmente. Sin embargo, las ventajas de las preferencias del usuario son tan grandes en algunos escenarios que los problemas con pequeñas desventajas no son tan importantes y se pueden resolver de manera relativamente fácil.

Así que dedicaré algo de tiempo a implementar dos demos que muestran cómo se puede implementar. Utilicé localStorage en mis demostraciones por muchas razones. Menciono solo dos de allí:

  1. Cookies es la forma en que se envía de forma permanente información diferente hacia o desde el servidor que realmente no se requiere. Aumenta el tamaño del encabezado HTTP y disminuye el rendimiento del sitio web (consulte aquí, por ejemplo).
  2. Las cookies tienen restricciones muy duras. Corresponde a la sección 6.3 de rfc2109 o 6.1 de rfc6265: Al menos 4096 bytes por cookie, al menos 50 cookies por dominio (20 en rfc2109), al menos 3000 cookies en total (300 en rfc2109). Entonces las cookies no se pueden usar para guardar demasiada información. Por ejemplo, si guarda el estado de cada cuadrícula de cada página web, puede alcanzar rápidamente los límites.

Por otro lado, localStorage es compatible con todos los navegadores modernos y será compatible con Internet Explorer a partir de IE8 (ver aquí ). localStorage se guardará automáticamente por orígenes (como a1.example.com, a2.example.com, a3.example.com, etc.) y tiene un límite arbitrario de 5 MB por origen (ver aquí ). Entonces, si usa el espacio cuidadosamente, estará lejos de cualquier límite.

Entonces usé en mis demos el localStorage . También debo mencionar que hay algunos complementos como jStorage que utilizan localStorage si es compatible con el navegador y usan otro almacenamiento, pero la misma interfaz para ti en el caso de navegadores antiguos como IE6 / IE7. En el caso de que tenga solo un menor tamaño de almacenamiento: 128 kB en lugar de 5 MB, pero es mejor que 4K que tiene para las cookies (ver aquí ).

Ahora sobre la implementación. Creo dos demos: esto y su versión extendida: esto .

En la primera demostración, los siguientes estados de la cuadrícula se guardarán y restaurarán automáticamente en la página de recarga ( F5 en la mayoría de los navegadores web):

  • qué columna están ocultas
  • el orden de las columnas
  • el ancho de cada columna
  • el nombre de la columna por la que se ordenará la cuadrícula y la dirección de clasificación
  • el número de página actual
  • el filtro actual de la cuadrícula y el indicador si se aplica el filtro. Usé multipleSearch: true configuración multipleSearch: true en la grilla.

Del mismo modo, uno puede ampliar (o reducir) la lista de opciones que son parte del estado de la grilla guardada.

Las partes más importantes del código de la demostración que encontrará a continuación:

 var $grid = $("#list"), saveObjectInLocalStorage = function (storageItemName, object) { if (typeof window.localStorage !== 'undefined') { window.localStorage.setItem(storageItemName, JSON.stringify(object)); } }, removeObjectFromLocalStorage = function (storageItemName) { if (typeof window.localStorage !== 'undefined') { window.localStorage.removeItem(storageItemName); } }, getObjectFromLocalStorage = function (storageItemName) { if (typeof window.localStorage !== 'undefined') { return $.parseJSON(window.localStorage.getItem(storageItemName)); } }, myColumnStateName = 'ColumnChooserAndLocalStorage.colState', saveColumnState = function (perm) { var colModel = this.jqGrid('getGridParam', 'colModel'), i, l = colModel.length, colItem, cmName, postData = this.jqGrid('getGridParam', 'postData'), columnsState = { search: this.jqGrid('getGridParam', 'search'), page: this.jqGrid('getGridParam', 'page'), sortname: this.jqGrid('getGridParam', 'sortname'), sortorder: this.jqGrid('getGridParam', 'sortorder'), permutation: perm, colStates: {} }, colStates = columnsState.colStates; if (typeof (postData.filters) !== 'undefined') { columnsState.filters = postData.filters; } for (i = 0; i < l; i++) { colItem = colModel[i]; cmName = colItem.name; if (cmName !== 'rn' && cmName !== 'cb' && cmName !== 'subgrid') { colStates[cmName] = { width: colItem.width, hidden: colItem.hidden }; } } saveObjectInLocalStorage(myColumnStateName, columnsState); }, myColumnsState, isColState, restoreColumnState = function (colModel) { var colItem, i, l = colModel.length, colStates, cmName, columnsState = getObjectFromLocalStorage(myColumnStateName); if (columnsState) { colStates = columnsState.colStates; for (i = 0; i < l; i++) { colItem = colModel[i]; cmName = colItem.name; if (cmName !== 'rn' && cmName !== 'cb' && cmName !== 'subgrid') { colModel[i] = $.extend(true, {}, colModel[i], colStates[cmName]); } } } return columnsState; }, firstLoad = true; myColumnsState = restoreColumnState(cm); isColState = typeof (myColumnsState) !== 'undefined' && myColumnsState !== null; $grid.jqGrid({ // ... other options page: isColState ? myColumnsState.page : 1, search: isColState ? myColumnsState.search : false, postData: isColState ? { filters: myColumnsState.filters } : {}, sortname: isColState ? myColumnsState.sortname : 'invdate', sortorder: isColState ? myColumnsState.sortorder : 'desc', loadComplete: function () { if (firstLoad) { firstLoad = false; if (isColState) { $(this).jqGrid("remapColumns", myColumnsState.permutation, true); } } saveColumnState.call($(this), this.p.remapColumns); } }); $grid.jqGrid('navButtonAdd', '#pager', { caption: "", buttonicon: "ui-icon-calculator", title: "choose columns", onClickButton: function () { $(this).jqGrid('columnChooser', { done: function (perm) { if (perm) { this.jqGrid("remapColumns", perm, true); saveColumnState.call(this, perm); } } }); } }); $grid.jqGrid('navButtonAdd', '#pager', { caption: "", buttonicon: "ui-icon-closethick", title: "clear saved grid's settings", onClickButton: function () { removeObjectFromLocalStorage(myColumnStateName); } }); 

Sea cuidadoso para definir myColumnStateName (el valor `'ColumnChooserAndLocalStorage.colState'``) en diferentes valores en las diferentes páginas.

La segunda demostración es la extensión de la primera usando la técnica de mi respuesta anterior a tu otra pregunta. La demostración utiliza la barra de herramientas de búsqueda y sincroniza, además, información entre el formulario de búsqueda avanzada y la barra de herramientas de búsqueda.

ACTUALIZADO : la siguiente respuesta contiene la versión extendida del código incluido anteriormente. Muestra cómo persistir las filas seleccionadas (o fila) adicionalmente. Otra respuesta muestra cómo persistir la lista de nodos expandidos de la cuadrícula de árbol y expandir los nodos en la redistribución de la página.