Używam GWT 2.1's CellBrowser z niestandardowym TreeViewModel
. TreeViewModel z kolei korzysta z AsyncDataProvider
do dynamicznego pobierania danych. To wszystko działa pięknie - kiedy użytkownik kliknie na węzeł, mój AsyncDataProvider pobiera wyniki przez RPC, a CellBrowser sumiennie je wyświetla.GWT: Jak programowo załadować CellBrowser?
Czuję się głupio, bo nie jestem w stanie tego obliczyć, ale w jaki sposób mogę programowo nakazać serwerowi CellBrowser ponowne załadowanie (i wyświetlenie) danych? Zgaduję, że muszę jakoś uzyskać uchwyt do AsyncDataProvider dla mojego węzła głównego, a następnie wywołać na nim updateRowData() & updateRowCount(), ale nie widzę oczywistego sposobu na zapytanie do przeglądarki (lub jej modelu) dla głównego DataProvider.
Chyba mógłbym dodać kod do mojego konstruktora AsyncDataProvider, który szuka argumentu zerowego, a przez to rozpoznać "hej, jestem rootem" i przechowywać gdzieś referencję, ale to wydaje się hackowe. Na pewno jest lepszy sposób na zrobienie tego.
Przepraszam za umieszczenie tutaj tak dużo kodu, ale nie wiem, jak to sprowadzić do czegoś prostszego i nadal zapewniać wystarczającą ilość kontekstu.
Moja 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();
}
}
Mój model:
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();
}
}
I wreszcie, oto jak mam je za pomocą:
CategoryTreeModel model = new CategoryTreeModel(selectionModel);
CellBrowser cellBrowser = new CellBrowser(model, null);
literówka na "HashRefresh", ale poza tym +1! :) – HaveAGuess
Dlaczego wszyscy głosują na tę odpowiedź? Ten poniżej jest znacznie lepszy - zmiana jednej linii, która to wszystko robi. –
updateRowData (start, response.getEntities()) aktualizuje wszystkie wyświetlacze dla providera, zamiast tego można użyć updateRowData (display, start, response.getEntities()). Ale display.setVisibleRangeAndClearData (display.getVisibleRange(), true) jest jeszcze lepszy :) – Quiz