AsyncListViewAdapter + SimplePager, why is inactive pager clearing the table? - gwt

EDIT: This seems to be a bug.
I'm trying to make CellTable work together with AsyncListViewAdapter<T> and SimplePager<T>. The data gets displayed, but when the pager should be 'deaf' (meaning when all existing data are displayed) it still receives clicks and, more importantly, makes the displayed data go away. Instead of my data 'loading' indicator gets displayed, and it keep loading and loading... Obviously nothing gets loaded, as it doesn't even call the onRangeChanged handler.
I went through the code-snippets in this thread, but I can't see anything suspicions on what I've been doing.
Is there some obvious answer to a rookie mistake?
I shrinked my variable names, hopefully it won't wrap too much.
protected class MyAsyncAdapter
extends AsyncListViewAdapter<DTO> {
#Override
protected void onRangeChanged(ListView<DTO> v) {
/*
* doesn't even get called on [go2start/go2end] click :(
*/
Range r = v.getRange();
fetchData(r.getStart(), r.getLength());
}
}
private void addTable() {
// table:
CellTable<DTO> table = new CellTable<DTO>(10);
table.addColumn(new Column<DTO, String>(new TextCell()) {
#Override
public String getValue(DTO myDto) {
return myDto.getName();
}
}, "Name");
// pager:
SimplePager<DTO> pager = new SimplePager<DTO>(table);
table.setPager(pager);
adapter = new MyAsyncAdapter();
adapter.addView(table);
// does not make any difference:
// adapter.updateDataSize(0, false);
// adapter.updateDataSize(10, true);
VerticalPanel vPanel = new VerticalPanel();
vPanel.add(table);
vPanel.add(pager);
RootLayoutPanel.get().add(vPanel);
}
// success-handler of my fetching AsyncCallback
#Override
public void onSuccess(List<DTO> data) {
// AsyncCallback<List<DTO>> has start field
adapter.updateViewData(start, data.size(), data);
if(data.size() < length)
adapter.updateDataSize(start + data.size(), true);
}
Regards
J. Záruba

Apparently because of a bug.

Related

How can I hide row/column headers in a NatTable?

I want to be able to add options to a right click menu of the NatTable that when clicked will cause either the row or column headers to be hidden but can be brought back as well.
The common practice is to operate on the corresponding DataLayer and modify the row height. Modifying the IDataProvider is typically not a good practice, as the IDataProvider is responsible for providing the data, not how the data should be rendered. So the following is an example of how to toggle the visibility of the column header layer (supposed that hideHeader is the flag to store the current state).
Button hideButton = new Button(buttonPanel, SWT.PUSH);
hideButton.setText("Hide/Show");
hideButton.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
this.hideHeader = !this.hideHeader;
if (this.hideHeader) {
columnHeaderDataLayer.setDefaultRowHeight(0);
} else {
columnHeaderDataLayer.setDefaultRowHeight(20);
}
natTable.refresh(false);
}
});
I know users who even used that approach to implement some sort of transition by slowly reducing the height to 0.
Alternatively you could use the RowResizeCommand if the column header DataLayer is not known
Button hideButton = new Button(buttonPanel, SWT.PUSH);
hideButton.setText("Hide/Show");
hideButton.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
this.hideHeader = !this.hideHeader;
if (this.hideHeader) {
natTable.doCommand(new RowResizeCommand(natTable, 0, 0));
} else {
natTable.doCommand(new RowResizeCommand(natTable, 0, 20));
}
}
});
I ended up solving this by changing the logic in the getColumnCount() method in my RowHeaderDataProvider to return 0 when flagged to be hidden, or 1 when flagged to be not hidden. Same applies for the getRowCount() in my ColumnHeaderDataProvider.

Dynamic DataGrid in GWT

I am trying to construct a DataGrid in GWT that will show an arbitrary dataset taken from an rpc method.
I have done some progress as I get the fields from a method and the data from another.
I have managed to construct the Datagrid and add the columns from the rpc.getFields() method and fill the table using an AsyncDataProvider.
The problem is that when I refresh the browser, it duplicates all the columns at the Datagrid. I cannot figure out what to do. I tried to remove first all the columns but no luck.
I attach the code if anyone have an idea.
public class MyCallBack implements AsyncCallback<List<Field>> {
DataGrid<Record> dg;
public MyCallBack(DataGrid<Record> dgrid) {
this.dg=dgrid;
}
public void onFailure(Throwable caught) {
Window.alert(caught.getMessage());
}
public void onSuccess(List<Field> result) {
for (int i=0;i<=result.size();i++) {
IndexedColumn ic = new IndexedColumn(i);
dg.addColumn(ic, result.get(i).getLabel());
}
}
public AsyncCallback<List<Field>> getCb() {
return this;
}
public void onModuleLoad() {
final DataGrid<Record> dg = new DataGrid<Record>();
MyCallBack mcb = new MyCallBack(dg);
DataProvider dp = new DataProvider();
DBConnectionAsync rpcService = (DBConnectionAsync) GWT.create(DBConnection.class);
ServiceDefTarget target = (ServiceDefTarget) rpcService;
String moduleRelativeURL = GWT.getModuleBaseURL() + "MySQLConnection";
target.setServiceEntryPoint(moduleRelativeURL);
rpcService.getFields(mcb.getCb());
dp.addDataDisplay(dg);
dg.setVisibleRange(0, 200);
SplitLayoutPanel slp = new SplitLayoutPanel();
slp.setHeight("700px");
slp.setWidth("1500px");
slp.addWest(dg, 770);
RootPanel.get().add(slp);
}
When you refresh a browser, all UI is lost. There is no difference between (a) show the UI for the first time or (b) show the UI after browser refresh.
Your comment "Only if I restart tomcat it works" suggests that the problem is on the server side. Most likely, you return twice the number of data points on a second call.
Try clearing the table before filling it like this:
public void onSuccess(List<Field> result) {
clearTable();
for (int i=0;i<=result.size();i++) {
IndexedColumn ic = new IndexedColumn(i);
dg.addColumn(ic, result.get(i).getLabel());
}
}
private void clearTable(){
while (dg.getColumnCount() > 0) {
db.removeColumn(0);
}
}

Smart GWT List Grid - Setting a hilite to a list grid on record click

I'm trying to set a hilite inside the record click handler of the list grid. I have tired the following code,
My hilites are as follows,
public static Hilite[] getWayBillSetHilites() {
return new Hilite[]{
new Hilite() {
{
setFieldNames("RECORD_VIEWED_STATUS");
setCriteria(new Criterion("RECORD_VIEWED_STATUS", OperatorId.EQUALS, "TRUE"));
setCssText(Constant.Css.TEXT_ITALIC_GRAY_32);
setTextColor("font-style:italic;color:#525252;");
setId("0");
}
}
};
}
record click handler of the grid appears as follows,
grid.addRecordClickHandler(new RecordClickHandler() {
#Override
public void onRecordClick(RecordClickEvent recordClickEvent) {
//gridWayBillSetGrid.getHiliteState()
//make RECORD_VIEWED_STATUS value "true"
recordClickEvent.getRecord().setAttribute("RECORD_VIEWED_STATUS", true);
gridWayBillSetGrid.enableHilite("0", true);
}
});
But when I click on the record, the styles are not showing up.
Please be kind to advise on this.
I think it's the wrong use case for hilites. Use getCellCSSText instead.
Try this one (override getCellCSSText method of ListGrid class):
ListGrid grid = new ListGrid(...){
#Override
protected String getCellCSSText(ListGridRecord record, int rowNum, int colNum) {
if("true".equalsIgnoreCase(record.getAttribute("RECORD_VIEWED_STATUS"))){
return "font-style:italic;color:#525252;";
}
return super.getCellCSSText(record, rowNum, colNum);
}
};

Calling refresh on another grid after removal

I currently have firstGrid that has some records, I have set a warning on removal message so a dialog box pops up when I click the delete button. How do I make it so secondGrid refresh when I confirm the delete on firstGrid?
firstGrid.setWarnOnRemoval(true);
firstGrid.setWarnOnRemovalMessage("Delete?");
SmartGwt doesn't support a customized behavior for this operation. You should program it by yourself.
Just create a new ListGridField and refresh your second grid in the CallBack after the remove operation. Your first approach could be the following:
ListGridField removeListGridField = new ListGridField("removeButton", 20);
removeListGridField.setType(ListGridFieldType.ICON);
removeListGridField.setCellIcon("[SKIN]actions/remove.png");
removeListGridField.setCanEdit(false);
removeListGridField.setCanFilter(false);
removeListGridField.setCanGroupBy(false);
removeListGridField.setCanSort(false);
removeListGridField.setCanDragResize(false);
removeListGridField.setCanFreeze(false);
removeListGridField.setCanHide(false);
removeListGridField.addRecordClickHandler(new RecordClickHandler()
{
#Override
public void onRecordClick(RecordClickEvent event)
{
if (event.getRecord() == null) // local record
{
discardEdits(event.getRecordNum(), 0);
yourGrid.fetchData();
}
else
removeData(event.getRecord(), new DSCallback()
{
#Override
public void execute(DSResponse dsResponse, Object data, DSRequest dsRequest)
{
yourGrid.fetchData();
}
});
}
});

Gwt sencha grid(requestfactory) not displaying data even when store has data

I have a sencha grid and it has a requestfactory to pull the data.
I can pull the data from the server but it does not show up.
I need to be able to make 2 selections from comboboxes and click a button to reload the grid. but it does not seem to work.
Here is the code -
#Override
public Widget asWidget() {
final ExplorerRequestFactory rf = GWT
.create(ExplorerRequestFactory.class);
rf.initialize(new SimpleEventBus());
RequestFactoryProxy<FilterPagingLoadConfig, PagingLoadResult<FlowerProxy>> proxy = new RequestFactoryProxy<FilterPagingLoadConfig, PagingLoadResult<FlowerProxy>>() {
#Override
public void load(
final FilterPagingLoadConfig loadConfig,
final Receiver<? super PagingLoadResult<FlowerProxy>> receiver) {
FlowerRequest req = rf.flowerRequest();
List<SortInfo> sortInfo = createRequestSortInfo(req,
loadConfig.getSortInfo());
req.getFlowers(vId, fId, loadConfig.getOffset(),
loadConfig.getLimit(), sortInfo).to(receiver);
req.fire();
}
};
loader = new PagingLoader<FilterPagingLoadConfig, PagingLoadResult<FlowerProxy>>(
proxy) {
#Override
protected FilterPagingLoadConfig newLoadConfig() {
return new FilterPagingLoadConfigBean();
}
};
loader.setRemoteSort(true);
FlowerProxyProperties props = GWT.create(FlowerProxyProperties.class);
ListStore<FlowerProxy> store = new ListStore<FlowerProxy>(props.id());
loader.addLoadHandler(new LoadResultListStoreBinding<FilterPagingLoadConfig, FlowerProxy, PagingLoadResult<FlowerProxy>>(
store) {
#Override
public void onLoad(
final LoadEvent<FilterPagingLoadConfig, PagingLoadResult<FlowerProxy>> event) {
LOG.info("Loader:addloadHondaler");
super.onLoad(event);
view.getView().refresh(false);
view.getView().layout();
//********Data successfully retrieved but does not populate the grid *********///
//**************************///
LOG.info("onLoad size:" + view.getStore().size()); //Data is present
}
});
final PagingToolBar toolBar = new PagingToolBar(50);
toolBar.getElement().getStyle().setProperty("borderBottom", "none");
toolBar.bind(loader);
ColumnConfig<FlowerProxy, String> nameColumn = new ColumnConfig<FlowerProxy, String>(
props.name(), 150, "Name");
ColumnConfig<FlowerProxy, Date> dateColumn = new ColumnConfig<FlowerProxy, Date>(
props.LastAccessDate(), 150, "Date");
dateColumn.setCell(new DateCell(DateTimeFormat
.getFormat(PredefinedFormat.DATE_SHORT)));
List<ColumnConfig<FlowerProxy, ?>> l = new ArrayList<ColumnConfig<FlowerProxy, ?>>();
l.add(nameColumn);
l.add(dateColumn);
ColumnModel<FlowerProxy> cm = new ColumnModel<FlowerProxy>(l);
view = new Grid<FlowerProxy>(store, cm);
view.getView().setForceFit(true);
view.setLoadMask(true);
view.setLoader(loader);
// Create the filters, and hook them to the loader and grid
GridFilters<FlowerProxy> filters = new GridFilters<FlowerProxy>(loader);
filters.initPlugin(view);
filters.addFilter(new DateFilter<FlowerProxy>(props.LastAccessDate()));
filters.addFilter(new StringFilter<FlowerProxy>(props.name()));
VerticalLayoutContainer con = new VerticalLayoutContainer();
con.setBorders(true);
con.setPixelSize(400, 300);
con.add(view, new VerticalLayoutData(1, 1));
con.add(toolBar, new VerticalLayoutData(1, -1));
return con.asWidget();
}
//********Call to this function should trigger a data pull and populate the grid ******///
/****************/
// Requestfactory call goes through, gets the data too but does not update the grid
public void reload(final String v, final String flower) {
LOG.info("V=> " + v + "\tFlower=> " + flower);
this.vId = v;
this.fId = flower;
LOG.info("Store size:" + view.getStore().size());
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
#Override
public void execute() {
if (v != null && flower != null && v.length() > 0
&& flower.length() > 0) {
loader.load();
LOG.info("Loader called");
}
}
});
}
Any ideas what I am missing here?
Without being able to run the code (as you didn't post the proxy, the server entity, the service proxy (aka request), or the service implementation, its a little hard to say, but I do see at least one thing definitely wrong, and others that may be confusing.
First and foremost, return the same instance from asWidget() each time it is called. The chain of events I am guessing is occurring that is confounding you:
App starts, something creates an instance of the widget where this asWidget method exists. In the course of setting it up, a store is created, as is a loader, and this.loader is assigned to that loader. The widget is added to the dom.
At some point, asWidget() is called a second time. This leaves the old grid attached (from the first time it was called), and creates a new grid, a new store, a new loader (and assigns to this.loader), but may not do anything with that new grid
Finally reload is called. This has a valid loader (the new one, not the old one), calls the server, populates the new store, which draws in the new grid. However, the old grid is still attached, so data never shows up.
With this fixed, you don't actually need to override any methods in LoadResultListStoreBinding - the base class will add items to the store, and the store will issue events that the grid is listening for.