GXT 3.0 LiveGrid with UIBinder
Has anyone been able to get the LiveGrid to work when using UIBinder? I've used the LiveGrid example from the Explorer demo as a general guide but it isn't working for me. The app hangs when I display the grid (I eventually get an UmbrellaException with an unhelpful stack trace -- stepping through with the debugger makes it look like I'm in an infinate loop where LiveGridView.refresh(boolean) is being called over and over).
When I use my implementation but change the LiveGridView to a Grid (in my component and my layout ui.xml file) and change the LiveToolItem to a PagingToolBar, it works perfectly.
If anyone can see what's amiss, I'd greatly appreciate it. Details of the component follow below:
My Layout file looks like this:
Code:
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:c="urn:import:com.sencha.gxt.widget.core.client"
xmlns:container="urn:import:com.sencha.gxt.widget.core.client.container"
xmlns:form="urn:import:com.sencha.gxt.widget.core.client.form"
xmlns:button="urn:import:com.sencha.gxt.widget.core.client.button"
xmlns:toolbar="urn:import:com.sencha.gxt.widget.core.client.toolbar"
xmlns:grid="urn:import:com.sencha.gxt.widget.core.client.grid">
<ui:with type="com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer.VerticalLayoutData"
field="topData">
<ui:attributes width="1" height=".25d"/>
</ui:with>
<ui:with type="com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer.VerticalLayoutData"
field="verticalLayoutData">
<ui:attributes width="1" height="-1"/>
</ui:with>
<ui:with type="com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer.VerticalLayoutData"
field="middleData">
<ui:attributes width="1" height="400d"/>
</ui:with>
<ui:with type="com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer.VerticalLayoutData"
field="bottomData">
<ui:attributes width="1" height="-1"/>
</ui:with>
<ui:with type="com.sencha.gxt.widget.core.client.grid.ColumnModel" field="cm"/>
<ui:with type="com.sencha.gxt.data.shared.ListStore" field="store"/>
<ui:with type="com.sencha.gxt.widget.core.client.grid.LiveGridView" field="view">
<ui:attributes stripeRows="true" forceFit="true" emptyText="No Results" cacheSize="5"></ui:attributes>
</ui:with>
<c:FramedPanel headingText="Item Finder" width="350" bodyStyle="background: none; padding: 5px">
<container:VerticalLayoutContainer>
<container:child layoutData="{verticalLayoutData}">
<c:FramedPanel headingText="Search Criteria" width="350" bodyStyle="background: none; padding: 5px"
collapsible="true">
<container:VerticalLayoutContainer>
<container:child layoutData="{verticalLayoutData}">
<form:FieldLabel text="Title">
<form:widget>
<form:TextField ui:field="title" allowBlank="true"/>
</form:widget>
</form:FieldLabel>
</container:child>
</container:VerticalLayoutContainer>
<c:button>
<button:TextButton text="Search" ui:field="searchButton"/>
</c:button>
<c:button>
<button:TextButton text="Create New" ui:field="createButton"/>
</c:button>
</c:FramedPanel>
</container:child>
<container:child layoutData="{verticalLayoutData}">
<c:FramedPanel headerVisible="false" width="350" bodyStyle="background: none; padding: 5px">
<container:VerticalLayoutContainer>
<container:child layoutData="{middleData}">
<grid:Grid ui:field="grid" cm="{cm}" store="{store}" view="{view}" loadMask="true"/>
</container:child>
<container:child layoutData="{bottomData}">
<toolbar:ToolBar ui:field="toolBar"></toolbar:ToolBar>
</container:child>
</container:VerticalLayoutContainer>
</c:FramedPanel>
</container:child>
</container:VerticalLayoutContainer>
</c:FramedPanel>
</ui:UiBinder>
and my Component looks like this:
Code:
package myco.mydom.myapp.webui.client.widgets;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Widget;
import myco.mydom.myapp.remoteservice.ItemGWTServiceAsync;
import myco.mydom.myapp.remoteservice.dto.PageResponse;
import myco.mydom.myapp.remoteservice.dto.ItemDto;
import myco.mydom.myapp.webui.client.data.ItemProperties;
import myco.mydom.myapp.webui.client.event.DomainUpdateEvent;
import myco.mydom.myapp.webui.client.event.DomainUpdateEventHandler;
import myco.mydom.myapp.webui.client.util.AppUtil;
import myco.mydom.myapp.webui.client.util.HandlerRegistrationWrapper;
import com.sencha.gxt.data.client.loader.RpcProxy;
import com.sencha.gxt.data.shared.ListStore;
import com.sencha.gxt.data.shared.loader.*;
import com.sencha.gxt.widget.core.client.Component;
import com.sencha.gxt.widget.core.client.Window;
import com.sencha.gxt.widget.core.client.button.TextButton;
import com.sencha.gxt.widget.core.client.event.RowDoubleClickEvent;
import com.sencha.gxt.widget.core.client.event.SelectEvent;
import com.sencha.gxt.widget.core.client.form.TextField;
import com.sencha.gxt.widget.core.client.grid.*;
import com.sencha.gxt.widget.core.client.toolbar.PagingToolBar;
import com.sencha.gxt.widget.core.client.toolbar.ToolBar;
import java.util.ArrayList;
import java.util.List;
public class ItemFinder extends Component {
interface ItemFinderUiBinder extends UiBinder<Widget, ItemFinder> {
}
private static ItemFinderUiBinder uiBinder = GWT.create(ItemFinderUiBinder.class);
private static final ItemGWTServiceAsync itemService = AppUtil.getItemService();
private Widget widget;
private final PagingLoader<PagingLoadConfig, PagingLoadResult<ItemDto>> loader;
private Long lastTotalCount;
@UiField
TextField title;
@UiField(provided = true)
ColumnModel<ItemDto> cm;
@UiField(provided = true)
ListStore<ItemDto> store;
@UiField
TextButton createButton;
@UiField
Grid<ItemDto> grid;
@UiField
LiveGridView<ItemDto> view;
@UiField
ToolBar toolBar;
@UiField
TextButton searchButton;
public ItemFinder() {
//this will also initialize store and columnModel
configureGridColumns();
RpcProxy<PagingLoadConfig, PagingLoadResult<ItemDto>> proxy = new RpcProxy<PagingLoadConfig, PagingLoadResult<ItemDto>>() {
@Override
public void load(final PagingLoadConfig loadConfig, final AsyncCallback<PagingLoadResult<ItemDto>> pagingLoadResultAsyncCallback) {
searchItems(loadConfig.getOffset(), loadConfig.getLimit(), new AsyncCallback<PageResponse<List<ItemDto>>>() {
@Override
public void onFailure(Throwable caught) {
pagingLoadResultAsyncCallback.onFailure(caught);
}
@Override
public void onSuccess(PageResponse<List<ItemDto>> result) {
PagingLoadResultBean<ItemDto> pageResult = new PagingLoadResultBean<ItemDto>();
pageResult.setOffset(loadConfig.getOffset());
pageResult.setData(result.getPayload());
if (result.getTotalCount() != null) {
lastTotalCount = result.getTotalCount();
}
pageResult.setTotalLength(lastTotalCount.intValue());
pagingLoadResultAsyncCallback.onSuccess(pageResult);
}
});
}
};
loader = new PagingLoader<PagingLoadConfig, PagingLoadResult<ItemDto>>(
proxy);
loader.addLoadHandler(new LoadResultListStoreBinding<PagingLoadConfig, ItemDto, PagingLoadResult<ItemDto>>(store));
widget = uiBinder.createAndBindUi(this);
grid.setLoader(loader);
toolBar.add(new LiveToolItem(grid));
}
private void configureGridColumns() {
ItemProperties props = GWT.create(ItemProperties.class);
List<ColumnConfig<ItemDto, ?>> cols = new ArrayList<ColumnConfig<ItemDto, ?>>();
cols.add(new ColumnConfig<ItemDto, String>(props.title(), 150, "Title"));
cols.add(new ColumnConfig<ItemDto, String>(props.campaignName(), 150, "Campaign"));
cm = new ColumnModel<ItemDto>(cols);
store = new ListStore<ItemDto>(props.key());
}
@Override
public Widget asWidget() {
return widget;
}
@UiHandler({"createButton", "searchButton"})
public void onButtonClick(SelectEvent event) {
if (event.getSource() == createButton) {
//no-op
} else if (event.getSource() == searchButton) {
lastTotalCount = null;
loader.load(0, view.getCacheSize());
}
}
@UiHandler("grid")
public void onSelectionChanged(RowDoubleClickEvent event) {
if (event.getRowIndex() >= 0) {
constructAndShowEditor(store.get(event.getRowIndex()));
}
}
private void searchItems(int offset, int pageSize, AsyncCallback<PageResponse<List<ItemDto>>> callback) {
itemService.searchItems(title.getValue(), null, offset, pageSize, callback);
}
}