2012-03-09 37 views
6

Utilizzo di Ext.ux.grid.FiltersFeature, dispongo di filtri remoti e sto tentando di scrivere una funzione per applicare un filtro data su una colonna della griglia a livello di codice (anziché fare clic sul menu a discesa del filtro nell'intestazione della colonna). La prima volta che eseguo la funzione, il grid store viene ricaricato senza il filtro. Quando eseguo la funzione una seconda volta (e successivamente ogni volta) funziona perfettamente, il negozio si ricarica con i filtri. Ecco l'essenza della funzione che ho:Applicare il filtro di griglia dalla funzione

// a filter object for testing 
aFilter = {type: 'date', field: 'a_date_field', comparison: 'gt', value: '2012-03-08 00:00:00'} 

var grid = Ext.create('Ext.grid.Panel', { 
    store: store, 
    features: [{ 
     ftype: 'filters', 
    }], 
    columns[{ 
     header: 'ID', 
     dataIndex: 'id', 
     itemId: 'id',    
     width: 40, 
    }, { 
     xtype: 'datecolumn', 
     header: 'Date', 
     dataIndex: 'a_date_field', 
     itemId: 'a_date_field', 
     width: 75, 
     format:'j-M-Y', 
     filterable: true 
    }], 
    listeners: { 
     'afterrender': function() { 

      // Need to create the filters as soon as the grid renders 
      // rather than waiting for the user to click on the header 
      grid.filters.createFilters(); 
     } 
    }, 
    bbar: [{ 
     text: 'Do a filter', 
     handler: function() { 

      // get the filter that is attached to the grid 
      var gridFilter = grid.filters.getFilter(aFilter.field); 

      // have to do this to create a menu for this filter 
      gridFilter.init({dataIndex: aFilter.field, type: aFilter.type, active: true}); 

      // if this column is a date filter column 
      if (gridFilter.type == 'date') { 
       var dateValue = Ext.Date.parse(aFilter.value, 'Y-m-d H:i:s'); 
       if (filter.comparison == 'gt') { 
        gridFilter.setValue({after: dateValue}); 
       } else { 
        gridFilter.setValue({before: dateValue}); 
       } 
      } 
     } 
    } 
}); 

Ho anche scoperto che questa funzione è la prima volta che se clicco su qualsiasi menu intestazione griglia prima di eseguire la funzione.

Ho cercato di scoprire quali modifiche sono apportate alla griglia che rendono il filtro funzionante dopo il primo tentativo non riesce o cosa fare clic su intestazione della griglia per fare funzionare il filtro. Ma niente di ciò che aggiungo sembra risolvere il problema in modo che venga eseguito la prima volta. Qualcuno l'ha implementato con successo?

+0

Hai provato a chiamare 'createFilter()' sull'oggetto 'FiltersFeature'? –

risposta

9

devo soluzione:

bbar: [{ 
    text: 'Do a filter', 
    handler: function() { 
     var grid = this.up('grid'); 
     var dateValue = Ext.Date.parse(aFilter.value, 'Y-m-d H:i:s'); 
     var value = aFilter.comparison == 'gt' ? {after: dateValue} : {before: dateValue}; 

     var gridFilter = grid.filters.getFilter(aFilter.field); 

     if (!gridFilter) { 
      gridFilter = grid.filters.addFilter({ 
       active: true, 
       type: aFilter.type, 
       dataIndex: aFilter.dataIndex, 
      }); 

      gridFilter.menu.show(); 
      gridFilter.setValue(value); 
      gridFilter.menu.hide(); 
     } else { 
      gridFilter.setActive(true); 
     } 

     Ext.Function.defer(function(){ 
      gridFilter = grid.filters.getFilter(aFilter.field); 
      gridFilter.setValue(value); 
     }, 10); 
    } 
}] 

Come potete vedere ho effettivamente applicare il filtro 2 volte.

+1

Grazie Lolo! Funziona alla grande. – Geronimo

+0

Wow @Lolo come sei arrivato al filtro di domanda due volte soluzione? C'è un bug che è stato presentato contro di esso? – dbrin

+0

@DmitryB Sono arrivato al punto in cui ha funzionato dopo il secondo clic del pulsante. Quindi il prossimo passo ovvio era provare a farlo subito. Non so se questo è un bug, probabilmente lo è. L'impostazione del valore causa l'accesso al menu, quindi deve essere visualizzato. Alla fine mi sembra che questa prima chiamata 'setValue' (inside if) non sia necessaria – Krzysztof

1

Ecco qualcosa che potrebbe valere la pena di esaminare. Sembra che il plug-in dei filtri stia ascoltando l'evento menucreate per inizializzare i filtri. Mi chiedo se il menu di creazione dell'evento sia differito fino a quando è necessario e quindi i filtri non vengono inizializzati?

/** 
* @private Handle creation of the grid's header menu. Initializes the filters and listens 
* for the menu being shown. 
*/ 
onMenuCreate: function(headerCt, menu) { 
    var me = this; 
    me.createFilters(); //<------ 
    menu.on('beforeshow', me.onMenuBeforeShow, me); 
}, 
+0

Grazie a Dmitry, ho provato a farlo manualmente ma non sembravo fare il trucco. Ho anche ottenuto il primo evento innescato dopo averlo allegato qui ma senza fortuna. Stava insidiando il menu, mostrandolo e nascondendolo fisicamente mentre Lolo suggeriva di gestirlo. – Geronimo

0

Si desidera applicare il filtro della griglia o la funzionalità store.filter() si adatta meglio? In questo caso basta filtrare il negozio e la griglia mostrerà i record filtrati.

+0

Gli utenti continueranno a filtrare la griglia in altri modi dopo aver applicato questo filtro, quindi ho bisogno di mantenere l'intestazione della griglia sincronizzata con il filtro. – Geronimo

0

Ho scoperto un altro modo per implementarlo. Sembra che le caratteristiche della griglia siano legate alla griglia solo dopo il rendering della griglia. Ciò significa che qualsiasi impostazione del filtro non avrà effetto fino a dopo il rendering della griglia. Il carico iniziale dell'archivio sembra essere iniziato prima che la griglia sia resa.

Ho risolto il problema creando il mio negozio con un proxy di memoria senza dati.

me.store = Ext.create('Ext.data.Store', { 
    model: 'SummaryData', 
    data: [], 
    proxy: { 
     type: 'memory', 
     reader: 'array' 
    }, 
    remoteSort: true, 
    remoteFilter: true 
}); 

quindi impostare un gestore afterrender sulla griglia per colpire nel proxy corretto e avviare un carico del negozio.

afterrender: function() { 
    var me = this; 

    me.store.setProxy({ 
     type: 'ajax', 
     url : '/print_unallocated/change_site__data', 
     reader: { 
      type: 'json', 
      root: 'rows' 
     }, 
     listeners: { 
      exception: function (proxy, response) { 
       Max.reportException(response); 
      } 
     } 
    }); 

    me.filters.createFilters(); 
    me.store.load(); 
}, 
6

come aggiornamento, ho ampliato questa funzione e modificato per funzionare con ExtJS 4.1.1

Ecco un esempio della funzione per impostare griglia filtri dinamicamente (senza che l'utente debba cliccare sulla voci del menu). Successivamente, gli elementi filtrati saranno visibili all'utente nei menu di intestazione della colonna della griglia come se li avesse cliccati e impostati manualmente.

L'argomento "griglia" è una griglia con FiltersFeature da filtrare. L'altro argomento è un array di oggetti "filter" (mostrerò un esempio sotto), la funzione applica semplicemente tutti gli oggetti "filtrati" passati alla griglia.

doGridFilter: function(grid, filters) { 

    // for each filter object in the array 
    Ext.each(filters, function(filter) { 
     var gridFilter = grid.filters.getFilter(filter.field); 

     gridFilter.setActive(true); 
     switch(filter.data.type) { 

      case 'date': 
       var dateValue = Ext.Date.parse(filter.data.value, 'm/d/Y'), 
        value; 

       switch (filter.data.comparison) { 

        case 'gt' : 
         value = {after: dateValue}; 
         break; 
        case 'lt' : 
         value = {before: dateValue}; 
         break; 
        case 'eq' : 
         value = {on: dateValue}; 
         break; 
       } 
       gridFilter = log.filters.getFilter(filter.field); 
       gridFilter.setValue(value); 
       gridFilter.setActive(true); 
       break; 

      case 'numeric': 
       var value; 

       switch (filter.data.comparison) { 

        case 'gt' : 
         value = {gt: filter.data.value}; 
         break; 
        case 'lt' : 
         value = {lt: filter.data.value}; 
         break; 
        case 'eq' : 
         value = {eq: filter.data.value}; 
         break; 
       } 
       gridFilter = log.filters.getFilter(filter.field); 
       gridFilter.setValue(value); 
       gridFilter.setActive(true); 
       break; 

      case 'list': 
       gridFilter = log.filters.getFilter(filter.field); 
       gridFilter.menu.setSelected(gridFilter.menu.selected, false); 
       gridFilter.menu.setSelected(filter.data.value.split(','), true); 
       break; 

      default : 
       gridFilter = log.filters.getFilter(filter.field); 
       gridFilter.setValue(filter.data.value); 
       break; 
     } 
    }); 
} 

Ecco un esempio di un array di oggetti "filtro".

// an example of a "filters" argument 
[{ 
    field: 'some_list_column_data_index', 
    data: { 
     type: 'list', 
     value: 'item1,item2,item3,item4,item5,item6,item7' 
    } 
}, { 
    field: 'some_date_column_data_index', 
    data: { 
     type: 'date', 
     comparison: 'gt', 
     value: '07/07/2007' 
    } 
}] 

Un avvertimento, è necessario "creare" manualmente i filtri prima di utilizzare questa funzione. Normalmente i filtri di griglia FiltersFeature vengono "creati" la prima volta che un utente fa clic su uno di essi, ciò potrebbe non accadere se l'utente desidera solo applicare uno di questi filtri predefiniti.

Questo può essere gestito facilmente includendo questo ascoltatore afterrender nel gridpanel.

listeners: { 

    // must create the filters after grid is rendered 
    afterrender: function(grid) { 
     grid.filters.createFilters(); 
    } 
} 
+0

Sto usando 4.1 e 4.2 il seguente restituisce un errore "filter.data.value.split (',') // non è una funzione" - filter.data.value sembra funzionare bene da solo – MarkyRoden

3

Basta aggiungere

filter: true 

alla descrizione colonne della griglia in questo modo:

me.columns = [ 
     {header:"Name", dataIndex:"name", editor:"textfield", filter: true}, 
    ]; 

se si vuole ottenere il lavoro del filtro dopo il primo tentativo, prima istanza creare.

0

Nella fonte, è possibile visualizzare un commento relativo a questo.

// Call getMenu() to ensure the menu is created, and so, also are the filters. We cannot call 
// createFilters() withouth having a menu because it will cause in a recursion to applyState() 
// that ends up to clear all the filter values. This is likely to happen when we reorder a column 
// and then add a new filter before the menu is recreated. 
me.view.headerCt.getMenu(); 

È possibile verificare se il menu è stato creato prima di applicare il filtro. Se non lo è, fallo da solo.

if(!grid.getView().headerCt.menu){ 
    grid.getView().headerCt.getMenu(); 
} 
Problemi correlati