2011-12-17 34 views
6

¿Cómo se prescribe la fila actual si se vuelve a abrir la cuadrícula o se actualiza la página?cómo mantener la fila actual en jqgrid

La respuesta en Persisting jqGrid column preferences describe cómo mantener el ancho de la columna y algunos otros parámetros.

En esta demostración de demostración hice clic en alguna fila y presioné F5. La fila anterior clicada no fue resaltada. ¿Cómo guardar/restaurar la fila actual en el almacenamiento local?

actualización

Si la estructura de la columna jqGrid se modifica en la aplicación y el usuario abre la aplicación desde el navegador de nuevo, restorecolumnstate crea colmodel nulo, cuando faltan algunos elementos. Esto causa una excepción en refreshSearchingToolbar que asume que todos los elementos de colmodel están presentes.

¿Cómo solucionar esto? ¿Cómo dedeccionar colmodol modificado y no restaurar colmodel en este caso? ¿O debería restaurarColumnState update colModel para que se cree la matriz adecuada?

** ** Actualización 2

Si myColumnsState.permutation contiene valores nulos $grid.jqGrid("remapColumns", myColumnsState.permutation, true) colmodel no válido creado. Aquí son capturas de pantalla de VS depurador inmediatamente antes y después remapColumns llaman

enter image description here

después:

after

me fijo Esta chaning código para

if (isColState && myColumnsState.permutation.length > 0) { 
     var i, isnull = false; 
     for (i = 0; i < myColumnsState.permutation.length; i = i + 1) { 
      if (myColumnsState.permutation[i] == null) { 
       isnull = true; 
       break; 
      } 
     } 
     if (!isnull) { 
      $grid.jqGrid("remapColumns", myColumnsState.permutation, true); 
     } 

¿Es esta la mejor solución ?

Respuesta

7

Combiné el código de the previous answer sobre las preferencias persistentes de la columna jqGrid con el código de another answer donde sugerí el código que implementó la selección persistente de filas. Es importante mencionar que en el caso de multiselect:true se usará la matriz de identificadores de las filas seleccionadas que contiene todos los seleccionados, incluso si las filas están en otra página. Es muy práctico y la implementación muy simple. Así que publiqué el correspondiente feature request, pero hasta el momento no he recibido respuesta.

Ahora puedo presentar dos demostraciones: the first demo que usan multiselect: true y the second demo que usa el mismo código, pero con la única selección.

Las partes más importantes del código que he usado se encontrarán a continuación.

Una cosa es muy importante mencionar: debe modificar el valor de myColumnStateName en cada página que use. El valor de la variable contiene el nombre del estado de la columna en el localStorage. Por lo tanto, si no cambia el nombre, compartirá el estado de diferentes tablas, lo que puede dar lugar a efectos muy extraños. Puede considerar usar nombres construidos a partir del nombre de la página actual o su URL como el valor de myColumnStateName.

var $grid = $("#list"), 
    getColumnIndex = function (grid, columnIndex) { 
     var cm = grid.jqGrid('getGridParam', 'colModel'), i, l = cm.length; 
     for (i = 0; i < l; i++) { 
      if ((cm[i].index || cm[i].name) === columnIndex) { 
       return i; // return the colModel index 
      } 
     } 
     return -1; 
    }, 
    refreshSerchingToolbar = function ($grid, myDefaultSearch) { 
     var postData = $grid.jqGrid('getGridParam', 'postData'), filters, i, l, 
      rules, rule, iCol, cm = $grid.jqGrid('getGridParam', 'colModel'), 
      cmi, control, tagName; 

     for (i = 0, l = cm.length; i < l; i++) { 
      control = $("#gs_" + $.jgrid.jqID(cm[i].name)); 
      if (control.length > 0) { 
       tagName = control[0].tagName.toUpperCase(); 
       if (tagName === "SELECT") { // && cmi.stype === "select" 
        control.find("option[value='']") 
         .attr('selected', 'selected'); 
       } else if (tagName === "INPUT") { 
        control.val(''); 
       } 
      } 
     } 

     if (typeof (postData.filters) === "string" && 
       typeof ($grid[0].ftoolbar) === "boolean" && $grid[0].ftoolbar) { 

      filters = $.parseJSON(postData.filters); 
      if (filters && filters.groupOp === "AND" && typeof (filters.groups) === "undefined") { 
       // only in case of advance searching without grouping we import filters in the 
       // searching toolbar 
       rules = filters.rules; 
       for (i = 0, l = rules.length; i < l; i++) { 
        rule = rules[i]; 
        iCol = getColumnIndex($grid, rule.field); 
        if (iCol >= 0) { 
         cmi = cm[iCol]; 
         control = $("#gs_" + $.jgrid.jqID(cmi.name)); 
         if (control.length > 0 && 
           (((typeof (cmi.searchoptions) === "undefined" || 
           typeof (cmi.searchoptions.sopt) === "undefined") 
           && rule.op === myDefaultSearch) || 
            (typeof (cmi.searchoptions) === "object" && 
             $.isArray(cmi.searchoptions.sopt) && 
             cmi.searchoptions.sopt.length > 0 && 
             cmi.searchoptions.sopt[0] === rule.op))) { 
          tagName = control[0].tagName.toUpperCase(); 
          if (tagName === "SELECT") { // && cmi.stype === "select" 
           control.find("option[value='" + $.jgrid.jqID(rule.data) + "']") 
            .attr('selected', 'selected'); 
          } else if (tagName === "INPUT") { 
           control.val(rule.data); 
          } 
         } 
        } 
       } 
      } 
     } 
    }, 
    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 JSON.parse(window.localStorage.getItem(storageItemName)); 
     } 
    }, 
    myColumnStateName = 'ColumnChooserAndLocalStorage2.colState', 
    idsOfSelectedRows = [], 
    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, 
       selectedRows: idsOfSelectedRows, 
       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; 
    }, 
    updateIdsOfSelectedRows = function (id, isSelected) { 
     var index = idsOfSelectedRows.indexOf(id); 
     if (!isSelected && index >= 0) { 
      idsOfSelectedRows.splice(index, 1); // remove id from the list 
     } else if (index < 0) { 
      idsOfSelectedRows.push(id); 
     } 
    }, 
    firstLoad = true; 

myColumnsState = restoreColumnState(cm); 
isColState = typeof (myColumnsState) !== 'undefined' && myColumnsState !== null; 
idsOfSelectedRows = isColState && typeof (myColumnsState.selectedRows) !== "undefined" ? myColumnsState.selectedRows : []; 

$grid.jqGrid({ 
    // ... some 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', 
    onSelectRow: function (id, isSelected) { 
     updateIdsOfSelectedRows(id, isSelected); 
     saveColumnState.call($grid, $grid[0].p.remapColumns); 
    }, 
    onSelectAll: function (aRowids, isSelected) { 
     var i, count, id; 
     for (i = 0, count = aRowids.length; i < count; i++) { 
      id = aRowids[i]; 
      updateIdsOfSelectedRows(id, isSelected); 
     } 
     saveColumnState.call($grid, $grid[0].p.remapColumns); 
    }, 
    loadComplete: function() { 
     var $this = $(this), i, count; 

     if (firstLoad) { 
      firstLoad = false; 
      if (isColState) { 
       $this.jqGrid("remapColumns", myColumnsState.permutation, true); 
      } 
      if (typeof (this.ftoolbar) !== "boolean" || !this.ftoolbar) { 
       // create toolbar if needed 
       $this.jqGrid('filterToolbar', 
        {stringResult: true, searchOnEnter: true, defaultSearch: myDefaultSearch}); 
      } 
     } 
     refreshSerchingToolbar($this, myDefaultSearch); 
     for (i = 0, count = idsOfSelectedRows.length; i < count; i++) { 
      $this.jqGrid('setSelection', idsOfSelectedRows[i], false); 
     } 
     saveColumnState.call($this, this.p.remapColumns); 
    }, 
    resizeStop: function() { 
     saveColumnState.call($grid, $grid[0].p.remapColumns); 
    } 
}); 

$grid.jqGrid('navGrid', '#pager', {edit: false, add: false, del: false}); 
$grid.jqGrid('navButtonAdd', '#pager', { 
    caption: "", 
    buttonicon: "ui-icon-closethick", 
    title: "clear saved grid's settings", 
    onClickButton: function() { 
     removeObjectFromLocalStorage(myColumnStateName); 
     window.location.reload(); 
    } 
}); 

ACTUALIZADO: Olvidé mencionar que en caso de uso multiselect: true opción con jqGrid 4.3 es muy importante utilizar the fix el que se describe aquí. En la primera demostración utilicé the modified version del jquery.jqGrid.src.js que incluye la corrección de errores.

ACTUALIZADO 2: Para facilitar la generación del nombre único del elemento de almacenamiento local utilizado para guardar el estado de la cuadrícula modifiqué un poco las demostraciones. La próxima versión de the multiselect demo y the single select demo uso myColumnStateName como la función define como la siguiente

var myColumnStateName = function (grid) { 
     return window.location.pathname + '#' + grid[0].id; 
    } 

El uso de myColumnStateName se cambian correspondientemente. Además extendí el estado de la columna para guardar el valor rowNum.

ACTUALIZADO 3:The answer describen cómo se puede utilizar la nueva posibilidad de jqGrid libre para guardar el estado de la cuadrícula.

+0

parche crítico de http://www.trirand.com/blog/?page_id=393/bugs/exception-after-successful-delete-in-complete-event-handler no se aplica. La eliminación remota siempre exitosa causa una excepción. – Andrus

+0

@Andrus: en las demostraciones que publiqué no hay operaciones de Eliminar, Agregar o Editar. Cómo se puede intentar sin excepción. – Oleg

+0

esto fue un comentario general, lo siento. ¿Cómo volver a utilizar este código para múltiples cuadrículas en páginas iguales y diferentes? ¿Puede jqgrid extenderse o subclasificarse con este código u otra idea? – Andrus

4

La solución de Oleg genera un error al actualizar la página como a continuación.

error: TypeError no detectada: No se puede leer la propiedad 'el' de la indefinida

Línea: 1936 en jquery.jqGrid.src.js

var previousSelectedTh = ts.grid.headers[ts.p.lastsort].el, newSelectedTh = ts.grid.headers[idxcol].el; 

solución a esto es para guardar el parámetro de rejilla y lastsort reinícielo cuando la carga se complete como se muestra a continuación.

saveColumnState = function(perm) { 
... 
    columnsState = { 
    search: this.jqGrid('getGridParam', 'search'), 
    page: this.jqGrid('getGridParam', 'page'), 
    sortname: this.jqGrid('getGridParam', 'sortname'), 
    sortorder: this.jqGrid('getGridParam', 'sortorder'), 
    lastsort: this.jqGrid('getGridParam', 'lastsort'), 
    permutation: perm, 
    colStates: { } 
    }, 
... 
}, 

loadComplete: function(data) { 
... 
    if (isColState) { 
    $this.jqGrid("remapColumns", myColumnsState.permutation, true); 
    if(myColumnsState.lastsort > -1) 
     $this.jqGrid("setGridParam", { lastsort: myColumnsState.lastsort }); 
    } 
... 
}, 
+0

Acabo de tener este problema, gracias por salvarme algunas horas de depuración :) – Charles

Cuestiones relacionadas