2011-01-15 1 views
9

Sto utilizzando GWT 2.1 CellBrowser con un numero personalizzato TreeViewModel. TreeViewModel utilizza a sua volta uno AsyncDataProvider per recuperare i dati dinamicamente. Tutto funziona alla perfezione: quando l'utente fa clic su un nodo, AsyncDataProvider preleva i risultati tramite RPC e CellBrowser li visualizza diligentemente.GWT: come ricaricare a livello di codice CellBrowser?

Mi sento sciocco per non essere in grado di capirlo, ma come posso dire a livello di codice al CellBrowser di ricaricare (e visualizzare) i dati? Sto indovinando che ho bisogno di ottenere in qualche modo un handle per AsyncDataProvider per il mio nodo radice e quindi chiamare updateRowData() & updateRowCount() su di esso, ma non vedo un modo ovvio per interrogare il browser (o il suo modello) per il root DataProvider.

Suppongo di poter aggiungere codice al mio costruttore AsyncDataProvider che cerca un argomento nullo, e in questo modo riconosco "hey, sono la radice" e memorizzo un riferimento da qualche parte, ma sembra logico. Sicuramente c'è un modo migliore per farlo.

Ci scusiamo per aver scaricato così tanto codice qui, ma non so come ridurlo a nulla di più semplice e fornire ancora un contesto sufficiente.

mio AsyncDataProvider:

private static class CategoryDataProvider extends AsyncDataProvider<Category> 
{   
    private Category selectedCategory; 

    private CategoryDataProvider(Category selectedCategory) 
    { 
     this.selectedCategory = selectedCategory; 
    } 

    @Override 
    protected void onRangeChanged(HasData<Category> display) 
    { 
     new AsyncCall<List<Category>>() 
     { 
      @Override 
      protected void callService(AsyncCallback<List<Category>> cb) 
      { 
       // default to root 
       String categoryId = "-1"; 
       if (selectedCategory != null) 
       { 
        categoryId = selectedCategory.getCategoryId(); 
       } 

       // when a category is clicked, fetch its child categories 
       service.getCategoriesForParent(categoryId, cb); 
      } 

      @Override 
      public void onSuccess(List<Category> result) 
      { 
       // update the display 
       updateRowCount(result.size(), true); 
       updateRowData(0, result); 
      } 
     }.go(); 

    } 
} 

Il mio modello:

private static class CategoryTreeModel implements TreeViewModel 
{ 
    private SingleSelectionModel<Category> selectionModel; 

    public CategoryTreeModel(SingleSelectionModel<Category> selectionModel) 
    { 
     this.selectionModel = selectionModel; 
    } 

    /** 
    * @return the NodeInfo that provides the children of the specified category 
    */ 
    public <T> NodeInfo<?> getNodeInfo(T value) 
    { 
     CategoryDataProvider dataProvider = new CategoryDataProvider((Category) value); 

     // Return a node info that pairs the data with a cell. 
     return new TreeViewModel.DefaultNodeInfo<Category>(dataProvider, new CategoryCell(), selectionModel, null); 
    } 

    /** 
    * @return true if the specified category represents a leaf node 
    */ 
    public boolean isLeaf(Object value) 
    { 
     return value != null && ((Category) value).isLeafCategory(); 
    } 
} 

E, infine, ecco come io li sto usando:

 CategoryTreeModel model = new CategoryTreeModel(selectionModel); 
     CellBrowser cellBrowser = new CellBrowser(model, null); 

risposta

10

Sembra che molte persone abbiano questo same issue. Ecco come ho gestito l'aggiornamento dei dati da un AsyncDataProvider.

Innanzitutto, creare un'interfaccia che aggiunga la possibilità di aggiornare il fornitore di dati avvolgendo il metodo protetto su RANGEChanged di AsyncDataProvider. Per esempio ...

HasRefresh.java

public interface HasRefresh<HasData<T>>{ 
    /** 
    * Called when a display wants to refresh 
    * 
    * @param display the display to refresh 
    */ 
    void refresh(HasData<T> display); 

} 

Poi il CellTable bisogno di essere aggiornati possono poi mettere in esso attraverso un'attività o comunque la vostra logica di controllo è stato configurato.

/** 
* A custom {@link AsyncDataProvider}. 
*/ 
public class MyAsyncDataProvider extends 
      AsyncDataProvider<Entity> implements HasRefresh<Entity> { 

      public void refresh(Entity display){ 

        onRangeChanged(display); 
      } 

      /** 
     * {@link #onRangeChanged(HasData)} is called when the table requests a 
     * new range of data. You can push data back to the displays using 
     * {@link #updateRowData(int, List)}. 
     */ 
     @Override 
     protected void onRangeChanged(
       HasData<Entity> display) { 
      currentRange = display.getVisibleRange(); 
      final int start = currentRange.getStart(); 

      dataServiceQuery = context.getEntities(); 

      dataServiceQuery 
        .execute(new DataServiceQueryHandler<Entity>() { 

         @Override 
         public void onQueryResponse(
           DataServiceQueryResponse<Entity> response) { 


          updateRowCount(response.getCount(), true); 
          updateRowData(start, response.getEntities()); 

         } 
        }); 

     }// end onRangeChanged() 

    }// end MyAsyncDataProvider class 
+0

typo su "HashRefresh" ma altrimenti +1! :) – HaveAGuess

+0

Perché tutti votano questa risposta? Quello sotto è molto meglio - un cambio di riga singolo che fa tutto questo. –

+0

updateRowData (start, response.getEntities()) aggiorna tutti i display per il provider, è possibile utilizzare updateRowData (display, start, response.getEntities()). Ma display.setVisibleRangeAndClearData (display.getVisibleRange(), true) è ancora meglio :) – Quiz

7

scoperto ora, il seguente codice è fondamentalmente la stessa, ma dall'interfaccia HasData invece di utilizzare AsyncDataProvider.

HasData<T> display; 
... 
display.setVisibleRangeAndClearData(display.getVisibleRange(), true); 
+0

Funziona per me! Grazie! –

2

Non capisco perché la risposta di affablebloke sia contrassegnata come "corretta" e svalutata così tanto !?

caffeina Coma ha chiesto circa l'aggiornamento di un browser cellulare e non una tabella cella, che sono cose totalmente diverse!

Per me, il seguente trucco ha funzionato: Io definisco il DataProvider s al di fuori del TreeViewModel e li passo come argomento al costruttore. Nel mio caso forniscono all'inizio strutture di dati vuote.

Ora si ha un riferimento allo DataProvider da "esterno" per aggiornare il Browser cella.

Esempio:

private class MyTreeViewModel implements TreeViewModel { 

    AbstractDataProvider<MyDataStructure> myDataProvider; 

    public MyTreeViewModel(AbstractDataProvider<MyDataStructure> myDataProvider) 
    { 
     this.myDataProvider = myDataProvider; 
    } 

    @Override 
    public <T> NodeInfo<?> getNodeInfo(T value) { 
     if(value == null) 
     { 
      // Level 0 
      return new DefaultNodeInfo<MyDataStructure>(myDataProvider, new MyCellImpl()); 
     } 
    } 
} 


AbstractDataProvider<MyDataStructure> myDataProvider = new ListDataProvider<MyDataStructure>(new ArrayList<MyDataStructure>()); // or AsyncDataProvider 
MyTreeViewModel myModel = new MyTreeViewModel(myDataProvider); 

CellBrowser<MyDataStructure> cellBrowser = new CellBrowser.Builder<MyDataStructure>(myModel, null).build(); 

/* 
    here you can do some stuff, for example, bind the CellBrowser to a template with UiBinder 
*/ 

/* 
if you use a ListDataProvider, do 
*/ 

myDataProvider.setList(myDataStructureFromSomewhere); 
myDataProvider.refresh(); 

/* 
if you use an AsyncDataProvider, do 
*/ 

myDataProvider.updateRowData(..., myDataStructureFromSomewhere); 
myDataProvider.updateRowCount(...); 
+0

Grazie per aver fornito questa risposta. Funziona perfettamente. Mi stavo chiedendo come aggiornare un CellBrowser per un po 'di tempo. –

0

Ho avuto lo stesso problema e questo ha funzionato per me:

List<TreeGridRecord> dataToTable = .... 

int firstPosition = this.pager.getDisplay().getVisibleRange().getStart(); 
this.dataProvider.updateRowData(firstPosition, dataToTable); 

int rowCount = this.pager.getPageStart() + dataToTable.size(); 
this.dataProvider.updateRowCount(rowCount, exactCount); 

dove il "pager" è una SimplePager per controllare l'impaginazione tavolo.

Spero che questo aiuti!