2012-02-06 34 views
17

En ExtJS 4.1 beta 2 logré implementar una cuadrícula de desplazamiento infinita con un almacenamiento remoto. Yo, básicamente, tomó una cuadrícula de paginación existente (en pleno funcionamiento) (con almacenamiento distante, filtrado y clasificación) y luego poner en las configuraciones adecuadas para el desplazamiento infinito:ExtJS Infinite Scroll Grid con filtros remotos y ordenar

// Use a PagingGridScroller (this is interchangeable with a PagingToolbar) 
verticalScrollerType: 'paginggridscroller', 
// do not reset the scrollbar when the view refreshs 
invalidateScrollerOnRefresh: false, 
// infinite scrolling does not support selection 
disableSelection: true, 

No dice esto en cualquier lugar en el docs (ver Sección Infinite Scrolling), pero necesita configurar su tienda para tener buffered: true config. Y no se puede cargar con store.load() que hay que hacer la siguiente manera:

store.prefetch({ 
    start: 0, 
    limit: 200, 
    callback: function() { 
     store.guaranteeRange(0, 99); 
    } 
}); 

Con todo eso, todo funciona muy bien si me desplazo lentamente y por lo tanto permiten que los datos de captación previa, no utilice ningún filtro y Don usar cualquier clasificación.

Sin embargo, si me desplazo rápidamente o trato de volver a cargar la cuadrícula de desplazamiento infinito con un filtro activo o al ordenarlo, todo se rompe. El error es options is undefined.

He pasado un par de horas haciendo algo de rastreo en el código y buscando en Google y aparte de concluir que nadie ha puesto en marcha una red de desplazamiento infinita con filtros a distancia y desplazamiento a distancia, he encontrado lo siguiente:

el filtrado se está rompiendo, porque de este método en Ext.data.Store que es llamada por el desplazador infinita cuando se necesita más datos desde el servidor:

mask: function() { 
    this.masked = true; 
    this.fireEvent('beforeload'); 
}, 

por alguna razón, este método dispara el evento beforeloadsin al Ext.data.Operation parámetro que se supone que es parte de él como se especifica here.

Como resultado, se produce un error en el controlador onbeforeload en Ext.ux.grid.FiltersFeature porque claro "opciones" no está definido:

/** 
* @private 
* Handler for store's beforeload event when configured for remote filtering 
* @param {Object} store 
* @param {Object} options 
*/ 
onBeforeLoad : function (store, options) { 

    options.params = options.params || {}; 
    this.cleanParams(options.params); 
    var params = this.buildQuery(this.getFilterData()); 
    Ext.apply(options.params, params); 

}, 

que puede cortar la llamada a este método mask a partir del código PagingScroller y luego el la funcionalidad de desplazamiento es genial. Puedo desplazarme tan rápido como me gusta y carga los datos correctamente. Pero luego filtra y ordena no se aplica a las solicitudes de ajax.

no he practicado tanto en el aspecto de la clasificación pero creo que es algo similar con este método porque mask tipo es simplemente otro elemento contenido por el objeto y causa operationningún objeto operación para ser pasado al Ajax solicitud.

Estoy pensando que si tan sólo pudiera encontrar la manera de forzar el método mask para disparar beforeload con el operation parámetros (como los documentos dicen que se supone que) todo estará bien. El problema es que no he podido averiguar cómo hacerlo. ¿Alguna sugerencia?

Si alguien me dice que estoy equivocado y la gente de hecho ha hecho este trabajo, estaría inspirado, pero un fragmento de las anulaciones que utilizó para manejar este problema o un enlace sería muy apreciado.

También he intentado degradar a 4.0.7 y 4.0.2a y obtengo los mismos resultados, por lo que no es solo un problema beta.

Actualización - 7 12 de febrero:

esto parece que puede ser en realidad no es un problema Ext.ux.grid.FilterFeature un problema de desplazamiento infinito. Si elimino la configuración FilterFeature, el desplazamiento completamente infinito funciona muy bien y pasa los parámetros de clasificación a mi backend cuando selecciono una columna. Comenzaré investigando el fin de las cosas de FilterFeature.

Respuesta

14

SUCCESS! Tengo un desplazamiento infinito trabajando con un filtro remoto y una ordenación remota (esto está en 4.1 beta 2, pero debido a que estaba obteniendo los mismos errores en 4.02a y 4.0.7 imagino que también los resolvería). Básicamente, solo tuve que agregar algunas modificaciones en mi código.

No he probado en otros navegadores, pero lo tengo en FF. Aquí están las sustituciones que estoy usando:

Ext.override(Ext.data.Store, { 

    // Handle prefetch when all the data is there and add purging 
    prefetchPage: function(page, options, forceLoad) { 

     var me = this, 
      pageSize = me.pageSize || 25, 
      start = (page - 1) * me.pageSize, 
      end = start + pageSize; 

     // A good time to remove records greater than cache 
     me.purgeRecords(); 

     // No more data to prefetch 
     if (me.getCount() === me.getTotalCount() && !forceLoad) { 
      return; 
     } 

     // Currently not requesting this page and range isn't already satisified 
     if (Ext.Array.indexOf(me.pagesRequested, page) === -1 && !me.rangeSatisfied(start, end)) { 
      me.pagesRequested.push(page); 

      // Copy options into a new object so as not to mutate passed in objects 
      options = Ext.apply({ 
       page  : page, 
       start : start, 
       limit : pageSize, 
       callback : me.onWaitForGuarantee, 
       scope : me 
      }, options); 
      me.prefetch(options); 
     } 
    }, 

    // Fixes too big guaranteedEnd and forces load even if all data is there 
    doSort: function() { 
     var me = this; 
     if (me.buffered) { 
      me.prefetchData.clear(); 
      me.prefetchPage(1, { 
       callback: function(records, operation, success) { 
        if (success) { 
         guaranteeRange = records.length < 100 ? records.length : 100 
         me.guaranteedStart = 0; 
         me.guaranteedEnd = 99; // should be more dynamic 
         me.loadRecords(Ext.Array.slice(records, 0, guaranteeRange)); 
         me.unmask(); 
        } 
       } 
      }, true); 
      me.mask(); 
     } 
    } 
}); 

Ext.override(Ext.ux.grid.FiltersFeature, { 

    onBeforeLoad: Ext.emptyFn, 

    // Appends the filter params, fixes too big guaranteedEnd and forces load even if all data is there 
    reload: function() { 
     var me = this, 
      grid = me.getGridPanel(), 
      filters = grid.filters.getFilterData(), 
      store = me.view.getStore(), 
      proxy = store.getProxy(); 

     store.prefetchData.clear(); 
     proxy.extraParams = this.buildQuery(filters); 
     store.prefetchPage(1, { 
      callback: function(records, operation, success) { 
       if (success) { 
         guaranteeRange = records.length < 100 ? records.length : 100; 
         store.guaranteedStart = 0; 
         store.guaranteedEnd = 99; // should be more dynamic 
         store.loadRecords(Ext.Array.slice(records, 0, guaranteeRange)); 
        store.unmask(); 
       } 
      } 
     }, true); 
     store.mask(); 
    } 
}); 

Mi tienda está configurado de este modo:

// the paged store of account data 
var store = Ext.create('Ext.data.Store', { 
    model: 'Account', 
    remoteSort: true, 
    buffered: true, 
    proxy: { 
     type: 'ajax', 
     url: '../list?name=accounts', //<-- supports remote filter and remote sort 
     simpleSortMode: true, 
     reader: { 
      type: 'json', 
      root: 'rows', 
      totalProperty: 'total' 
     } 
    }, 
    pageSize: 200 
}); 

La rejilla es:

// the infinite scroll grid with filters 
var grid = Ext.create('Ext.grid.Panel', { 
    store: store, 
    viewConfig: { 
     trackOver: false, 
     singleSelect: true, 
    }, 
    features: [{ 
     ftype: 'filters', 
     updateBuffer: 1000 // trigger load after a 1 second timer 
    }], 
    verticalScrollerType: 'paginggridscroller', 
    invalidateScrollerOnRefresh: false,   
    // grid columns 
    columns: [columns...], 
}); 

también la carga inicial debe ser hecho como éste (no solo store.load()):

store.prefetch({ 
    start: 0, 
    limit: 200, 
    callback: function() { 
     store.guaranteeRange(0, 99); 
    } 
});  
4

Su respuesta proporciona la dirección correcta, he modificado el código de

store.loadRecords(Ext.Array.slice(records, 0, count)); 

a

store.loadRecords(Ext.Array.slice(records, 0, records.length)); 

Esto ha solucionado un problema de su filtro anterior devolver resultados vacíos. Después de insertar este cambio, estaba funcionando correctamente.

+1

Buen lugar. Veo lo que estás diciendo, creo: cuando la tienda se reduce a menos del rango de garantía, el rango de garantía se mantiene en esa cantidad y no se cargará más. Sin embargo, el problema con su solución es que el rango de garantía será del mismo tamaño que la tienda y no realizará la búsqueda previa como resultado, esto significa que cuando la cuadrícula se desplaza normalmente, nunca se volverá a cargar una vez que pase la fila 200 o lo que sea el tamaño de página es. Agregué una solución en la anulación, simplemente no es muy dinámica. La variable guaranteeRange la he establecido en 100 estática porque eso es lo que es mío. – Geronimo

Cuestiones relacionadas