Persistindo as preferências da coluna jqGrid

Eu tenho alguns jqGrids no meu aplicativo ASP.NET MVC 3 que tem um número de colunas. Eu adicionei o seguinte às definições de coluna para padronizar algumas colunas para serem ocultas:

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

e isso funciona bem. Essas colunas não são visíveis na minha grade.

Então eu adicionei isso para implementar o seletor de coluna:

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

Ótimo, traz o seletor de colunas agora. Em seguida, adicionei o seguinte às colunas que nunca quis mostrar no seletor de colunas:

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

Então eu posso agora esconder / mostrar colunas muito bem. Agora, como você persistiria essa informação? DB? Como um biscoito? Outro jeito? Existe uma maneira preferida de armazenar esse tipo de informação que é realmente uma preferência do usuário em vez de algo relacionado aos dados em si?


Mais informações

Com base no comentário de Oleg abaixo, quero fornecer um pouco mais de informação.

O ponto aqui é que eu tenho grades com 10-15 colunas que podem ser exibidas com base na preferência do usuário. Por um exemplo simples, uma das minhas grades possui as 9 colunas a seguir:

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

Os usuários podem ocultar / mostrar qualquer uma dessas 9 colunas com base em suas preferências pessoais.

O que eu quero fazer é fornecer uma maneira de persistir quais colunas um determinado usuário deseja ver, para que ele / ela não precise re-escolher essas colunas para ver cada vez que a página com essa grade é mostrada.

Eu achei você pergunta muito interessante. A questão sobre salvar o estado do usuário da grade é interessante em muitos casos. Existem algumas respostas interessantes sobre esses problemas que usam cookies (veja aqui, por exemplo).

Na minha opinião salvar o estado da grade no database no servidor ou no localStorage é melhor maneira como o uso de cookie. A melhor maneira depende dos requisitos do projeto em que você o usa. Por exemplo, o uso do armazenamento do database no servidor permite implementar o estado de roaming da grade. Se você usar o localStorage vez de cookies, as preferências do usuário serão perdidas se o usuário for para outro computador ou apenas se o usuário usar outro navegador da Web no mesmo computador.

Outro problema com o estado da grade é a manutenção. As informações sobre as colunas da grade que você mantém normalmente nos arquivos JavaScript ou HTML e não no database. No caso, as duas fonts podem não ser síncronas nas alterações na grade. Diferentes cenários do problema de atualização você poderia imaginar. No entanto, as vantagens das preferências do usuário são tão grandes em alguns cenários que os problemas com pequenas desvantagens não são tão importantes e podem ser resolvidos de forma relativamente fácil.

Então, vou gastar algum tempo para implementar duas demonstrações que mostram como ela pode ser implementada. Eu usei o localStorage em minhas demos por muitos motivos. Eu menciono apenas dois de lá:

  1. Cookies é o meio que envia informações permanentemente diferentes para ou do servidor, o que não é realmente necessário. Aumenta o tamanho do header HTTP e diminui o desempenho do site (veja aqui, por exemplo).
  2. Os cookies têm restrições muito difíceis. Corresponde à seção 6.3 do rfc2109 ou 6.1 do rfc6265: Pelo menos 4096 bytes por cookie, pelo menos 50 cookies por domínio (20 no rfc2109), pelo menos 3000 cookies no total (300 no rfc2109). Portanto, os cookies não podem ser usados ​​para salvar muitas informações. Por exemplo, se você salvasse o estado de cada grade de cada página da Web, poderá atingir rapidamente os limites.

Por outro lado, o localStorage é suportado por todos os navegadores modernos e terá suporte no Internet Explorer a partir do IE8 (veja aqui ). O localStorage será salvo automaticamente por origens (como a1.example.com, a2.example.com, a3.example.com, etc) e tem limite arbitrário de 5 MB por origem (veja aqui ). Então, se você usar o espaço com cuidado, você estará longe de qualquer limite.

Então eu usei em minhas demos o localStorage . Além disso, devo mencionar que existem alguns plug-ins como o jStorage, que usam o localStorage se ele for suportado pelo navegador e usar outro armazenamento, mas a mesma interface para você no caso de navegadores antigos como o IE6 / IE7. No caso você tem apenas um tamanho menor de armazenamento: 128 kB ao invés de 5 MB, mas é melhor que 4K para cookies (veja aqui ).

Agora sobre a implementação. Eu crio duas demos: esta e sua versão estendida: isso .

Na primeira demonstração, os seguintes estados da grade serão salvos e restaurados automaticamente no recarregamento da página ( F5 na maioria dos navegadores da Web):

  • quais colunas estão escondidas
  • a ordem das colunas
  • a largura de cada coluna
  • o nome da coluna pela qual a grade será ordenada e a direção da sorting
  • o número da página atual
  • o filtro atual da grade e o sinalizador se o filtro é aplicado. Eu usei multipleSearch: true setting na grade.

Da mesma forma, pode-se estender (ou reduzir) a lista de opções que fazem parte do estado da grade salva.

As partes mais importantes do código da demonstração você encontrará abaixo:

 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); } }); 

Seja cuidadosamente para definir myColumnStateName (o valor `'ColumnChooserAndLocalStorage.colState'`` na demonstração) para diferentes valores nas diferentes páginas.

A segunda demo é a extensão da primeira usando a técnica da minha antiga resposta à sua outra pergunta. A demonstração usa a barra de ferramentas de pesquisa e sincroniza informações adicionais entre o formulário de pesquisa avançada e a barra de ferramentas de pesquisa.

ATUALIZADO : A próxima resposta contém a versão estendida do código incluído acima. Ele mostra como persistir as linhas selecionadas (ou linha) adicionalmente. Outra resposta mostra como persistir a lista de nós expandidos da grade da tree e expandir os nós no relançamento da página.