Pregunta

I want to have on my page created with UIBinder a CellTable with data, received from server. I think I dont quite understand the logic of UiBinder. What steps should I do before calling initWidget(), and what I shouldn't ?
When I remove the call to configureDataProvider() the table appears, but it is empty, with progress bar running. When I include configureDataProvider(), the table is not rendered at all.

Please can you explain what is happening here?

@UiField(provided = true)
VerticalPanel tableSelection;

@UiField(provided = true)
Anchor productTableAnchor;

@UiField(provided = true)
Anchor ordersTableAnchor;

@UiField(provided = true)
Anchor staffTableAnchor;
List<ProductDTO> products;

@UiField(provided = true)
CellTable<ProductDTO> productTable;

@UiField(provided = true)
SimplePager pager;

public TableSelectionWidget() {
SimplePager.Resources pagerResources = GWT
    .create(SimplePager.Resources.class);
tableSelection = new VerticalPanel();
productTableAnchor = new Anchor();
ordersTableAnchor = new Anchor();
staffTableAnchor = new Anchor();
productTable = new CellTable<ProductDTO>();
productTable.setPageSize(10);
configureTable();
pager = new SimplePager(TextLocation.CENTER, pagerResources, false, 0,
    true);
pager.setDisplay(productTable);
initWidget(uiBinder.createAndBindUi(this));
}

private void configureTable() {
Column<ProductDTO, String> nameColumn = new Column<ProductDTO, String>(
    new TextCell()) {
    @Override
    public String getValue(ProductDTO object) {
    return object.getName();
    }
};
Column<ProductDTO, String> priceColumn = new Column<ProductDTO, String>(
    new TextCell()) {
    @Override
    public String getValue(ProductDTO object) {
    return object.getPrice().toString();
    }
};
Column<ProductDTO, String> quantityColumn = new Column<ProductDTO, String>(
    new TextCell()) {
    @Override
    public String getValue(ProductDTO object) {
    return String.valueOf(object.getQuantity());
    }
};
productTable.addColumn(nameColumn, "Name");
productTable.addColumn(priceColumn, "Price");
productTable.addColumn(quantityColumn, "Qty");

configureDataProvider();

}

private void configureDataProvider() {
AsyncDataProvider<ProductDTO> provider = new AsyncDataProvider<ProductDTO>() {
    @Override
    protected void onRangeChanged(HasData<ProductDTO> display) {
    final int start = display.getVisibleRange().getStart();
    int length = display.getVisibleRange().getLength();
    AsyncCallback<List<ProductDTO>> callback = new AsyncCallback<List<ProductDTO>>() {
        public void onFailure(Throwable caught) {
        Window.alert(caught.getMessage());
        }

        public void onSuccess(List<ProductDTO> result) {
        products = result;
        updateRowData(start, result);
        }
    };

    productService.getAllProducts(callback);
    }
};

provider.addDataDisplay(productTable);
provider.updateRowCount(products.size(), true);
}

EDIT Added ui.xml

    <!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
    xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:c="urn:import:com.google.gwt.user.cellview.client"
    xmlns:ct="urn:import:com.ooo1sk.client.widgets">
    <ui:style>
    </ui:style>
    <g:HTMLPanel>
        <g:VerticalPanel styleName="" ui:field="tableSelection">
            <g:Anchor ui:field="ordersTableAnchor" text="Orders"></g:Anchor>
            <g:Anchor ui:field="productTableAnchor" text="Product"></g:Anchor>
            <g:Anchor ui:field="staffTableAnchor" text="Staff"></g:Anchor>
        </g:VerticalPanel>
        <g:HTMLPanel>
            <table cellspacing='0' cellpadding='0' style='width:100%;'>
                <tr>
                    <td valign='top'>
                        <c:CellTable addStyleNames='infoTable' pageSize='15'
                            ui:field='productTable' />
                    </td>
                </tr>
                <tr>
                    <td align='center'>
                        <c:SimplePager ui:field='pager' />
                    </td>
                </tr>
            </table>
        </g:HTMLPanel>
    </g:HTMLPanel>
</ui:UiBinder> 

UPD: after changes it works, but keeps showing me only the first 15 rows, however Pager shows all 91 rows and changes number after clicking.

 private void configureDataProvider() {

    AsyncDataProvider<ProductDTO> provider = new AsyncDataProvider<ProductDTO>() {
        @Override
        protected void onRangeChanged(HasData<ProductDTO> display) {
        final int start = display.getVisibleRange().getStart();
        final int length = display.getVisibleRange().getLength();
   
        productService
            .getAllProducts(new AsyncCallback<List<ProductDTO>>() {

                public void onSuccess(List<ProductDTO> result) {
                label.setText("start " + start + " "
                    + "resultsize " + result.size() + " "
                    + "length " + length);
                products = result;
                updateRowCount(result.size(), true);
                updateRowData(start, result);

                }

                public void onFailure(Throwable caught) {
                Window.alert(caught.getMessage());
                }
            });
        }
    };
    provider.addDataDisplay(productTable);
    }

Ok, playing with numbers fixed the issue. in updateRowData(start, result); I changed start to 0 and it works fine now. Still, I would greatly appreciate any comment of experts on this.

¿Fue útil?

Solución

The initWidget(Widget widget) is a method of the Composite class used to initialize itself as a wrapper for a possible inner aggregation of widgets. Generally you create a composition of widgets rooted on a given widget and then pass it to the initiWidget() method. This way, the rooted element is not exposed (in terms of its methods) but still acts as if it was never wrapped.

In your sample you have UiBinder takes care of defining the UI, so you pass to such method the return of the binding creation (uiBinder.createAndBindUi(this)). Before this call (actually, before the createAndBindUi(), but generally it is tied to the initWidget()), you must instantiate all your widget marked with @UiField(provided = true) i.e., all those who need a proper initialization otherwise impossible in plain UiBinder style. In your case, you don't need to mark everything provided = true, only the CellTable requires that (for the specialization).

Back to your problem, if you remove the configureDataProvider() call, you will never set up the AsyncDataProvider and simply you will see no data at all (the spinning gif is because somewhere - can't remember where now - the row count has been set to 0). If you enable it, the call to addDataDisplay() will implicitly force a range update that will end up calling the AsyncDataProvider to request your data.

The problem is that you do not update both the row data and the row count at the same time in the onSuccess() callback. See here.

Also, you don't need to call updateRowCount() after addDataDisplay(), otherwise two requests will be made to retrieve the same initial data, which is unnecessary.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top