-
1 May 2012 10:02 AM #1
GXT 3.0 LiveGrid with UIBinder
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:
and my Component 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>
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); } }
-
1 May 2012 10:10 AM #2
Have you tried to use the same code without UiBinder? Do you have a fully working testcase implementing EntryPoint?
It should not make a difference if you use UiBinder or not. The behaviour should be the same.
-
1 May 2012 10:21 AM #3
I changed the official example of the LiveGridView to use UiBinder and it works without any problems for me.
-
1 May 2012 11:12 AM #4
I've created a test case that can reproduce the problem. In my example, the LiveGrid is inside a tab. It works fine when the grid is in the first tab (i.e. if it's visible when the page first loads) if I put the exact same component in the second tab, however, I get the same problem I described above. Is there somewhere I can upload the test case (or email it to you), it's spread across a few files so I don't think you'd want me to in-line it in this post.
-
1 May 2012 11:15 AM #5
You can zip it up and attach it here. I will move this thread to the bugs forum.
-
1 May 2012 11:18 AM #6
Sorry, I didn't see that attach button for some reason. Test case now attached.
liveGridtestcase.zip
Thank you for reporting this bug. We will make it our priority to review this report.


Reply With Quote