How to Display Wicket DataTable or List View row items for an Object which has a List of Objects as a field - wicket

AID BID count1 count2
AID1 1 3 4
2 4 5
3 4 2
AID2 4 6 10
5 2 4
6 4 6
AID3 7 4 5
8 9 4
THis is the table I am trying to display that is for every AID in ObjA display a list of ObjB s.
I want to display a Sortable data using Wicket DataTable or Listview .I have used the SortableData Provider and it works for simple Objects like
ObjA{
int a;
String b;
}
But I have an Object which has List of Objects within it as field as shown below.
ObjA{
Long aId;
List<ObjB> listObjB;
}
#magomi
Thank you for your response.This is the code and the corresponding Html files. I am using DataTables.
I am not sure how to render the items in the listObjBs (bID,count,count2) in the table for every aID.
What is the right way to add the columns for the listObjBs in the ObjA
***columns.add(new PropertyColumn<ObjA>(Model.of("B ID"), "ObjBCounts.bID",
"ObjBCounts.BID"));
columns.add(new PropertyColumn<ObjA>(Model.of(" Count"), "objBCounts.count"));
columns.add(new PropertyColumn<ObjA>(Model.of("Count2”),"objBCounts.count2"));***
How do I sort on the column bID in the iterator method?
Public class HomePage extends Webpage
private static List<ObjB> listObjBs = Arrays.asList(
new ObjB(15L,2,5),
new ObjB(12L,7,10),
new ObjB(13L,3,5),
new ObjB(10L,6,5));
private static List<ObjA> contacts = Arrays.asList(
new ObjA(1L,listObjBs),
new ObjA(2L,listObjBs),
new ObjA(3L,listObjBs),
new ObjA(4L,listObjBs));
public HomePage(final PageParameters parameters) {
List<IColumn<ObjA>> columns = new ArrayList<IColumn<ObjA>>();
columns.add(new PropertyColumn<ObjA>(Model.of("A ID"), "aID",
"aID"));
Public class HomePage extends Webpage
private static List<ObjB> listObjBs = Arrays.asList(
new ObjB(15L,2,5),
new ObjB(12L,7,10),
new ObjB(13L,3,5),
new ObjB(10L,6,5));
private static List<ObjA> contacts = Arrays.asList(
new ObjA(1L,listObjBs),
new ObjA(2L,listObjBs),
new ObjA(3L,listObjBs),
new ObjA(4L,listObjBs));
public HomePage(final PageParameters parameters) {
List<IColumn<ObjA>> columns = new ArrayList<IColumn<ObjA>>();
columns.add(new PropertyColumn<ObjA>(Model.of("A ID"), "aID",
"aID"));
columns.add(new PropertyColumn<ObjA>(Model.of("B ID"), "ObjBCounts.bID",
"ObjBCounts.BID"));
columns.add(new PropertyColumn<ObjA>(Model.of(" Count"), "objBCounts.count"));
columns.add(new PropertyColumn<ObjA>(Model.of("Count2”),"objBCounts.count2"));
add(new DefaultDataTable<ObjA>("contacts", columns,
new ContactsProvider(), 10));
}
rivate static class ContactsProvider extends SortableDataProvider<ObjA> {
public ContactsProvider() {
setSort("aID", SortOrder.ASCENDING);
}
public Iterator<? extends ObjA> iterator(int first, int count) {
List<ObjA> data = new ArrayList<ObjA>(contacts);
Collections.sort(data, new Comparator<ObjA>() {
public int compare(ObjA o1, ObjA o2) {
int dir = getSort().isAscending() ? 1 : -1;
if ("bID".equals(getSort().getProperty())) {
return dir * (o1.listObjB.get(0).getBID().compareTo(o2.listObjB.get(0).getBID()));
} else {
return dir * (o1.getAID().compareTo(o2.getAID()));
}
}
});
return data.subList(first, Math.min(first + count, data.size()))
.iterator();
}
public int size() {
return contacts.size();
}
public IModel<ObjA> model(ObjA object) {
return Model.of(object);
}
}
<html>
<body>
<table border ="1" cellspacing = "1" wicket:id="contacts" class="contacts"></table>
</body>
</html>
add(new DefaultDataTable<ObjA>("contacts", columns,
new ContactsProvider(), 10));
}
rivate static class ContactsProvider extends SortableDataProvider<ObjA> {
public ContactsProvider() {
setSort("aID", SortOrder.ASCENDING);
}
public Iterator<? extends ObjA> iterator(int first, int count) {
List<ObjA> data = new ArrayList<ObjA>(contacts);
Collections.sort(data, new Comparator<ObjA>() {
public int compare(ObjA o1, ObjA o2) {
int dir = getSort().isAscending() ? 1 : -1;
if ("bID".equals(getSort().getProperty())) {
return dir * (o1.listObjB.get(0).getBID().compareTo(o2.listObjB.get(0).getBID()));
} else {
return dir * (o1.getAID().compareTo(o2.getAID()));
}
}
});
return data.subList(first, Math.min(first + count, data.size()))
.iterator();
}
public int size() {
return contacts.size();
}
public IModel<ObjA> model(ObjA object) {
return Model.of(object);
}
}
<html>
<body>
<table border ="1" cellspacing = "1" wicket:id="contacts" class="contacts"></table>
</body>
</html>
ObjB{
Long bId;
int count;
int count2;
}
It want to display data from ObjA which contains a list of objBs in a Sortable table
Could some one please help me with the wicket markup and and how to populate the columns.
Thank you.

I'm not quite sure but it looks like you are mixing ObjA and ObjB into one table in a way that is not possible. Is it right, you want to show a table of ObjA (at least this is indicated by your first column)? Or do you want to show a table of ObjB (as indicated by the second and third column)?
As long as a table is backed by one list you cannot mix another list into this table.
From my sight you have the following options:
You can can have a table of ObjA and inside a table cell you can have a panel with a table of ObjB. But there is no sorting over all rows of ObjB of all ObjA.
You can define some kind of DTO that has a object mixed from ObjA and ObjB. Something like this:
class Data() {
int objAId;
int objBId;
int count1;
int count2;
...
}
You can use a standard repeating view and implement the sorting into your own data provider.

Related

Delete Multiple rows from Nattable

I am trying to delete more than one row from NatTable. Following the solution described in Delete rows from Nattable. I have created a the following classes:
the Command class looks like this :
public class DeleteMultiRowCommand extends AbstractMultiRowCommand {
public DeleteMultiRowCommand(AbstractMultiRowCommand command) {
super(command);
}
protected DeleteMultiRowCommand(ILayer layer, int[] rowPositions) {
super(layer, rowPositions);
}
#Override
public ILayerCommand cloneCommand() {
return new DeleteMultiRowCommand(this);
}
}
Command Handler class:
public class DeleteMultiRowCommandHandler<T> implements ILayerCommandHandler<DeleteMultiRowCommand> {
private List<T> bodyData;
private SelectionLayer layer;
public DeleteMultiRowCommandHandler(List<T> bodyData, SelectionLayer selectionLayer) {
this.bodyData = bodyData;
this.layer = selectionLayer;
}
public DeleteMultiRowCommandHandler(List<T> bodyData){
this.bodyData = bodyData;
}
#Override
public Class<DeleteMultiRowCommand> getCommandClass() {
return DeleteMultiRowCommand.class;
}
#Override
public boolean doCommand(ILayer targetLayer, DeleteMultiRowCommand command) {
//convert the transported position to the target layer
if (command.convertToTargetLayer(targetLayer)) {
Collection<Integer>rowpos = command.getRowPositions();
//remove the element
for(Integer val : rowpos){
this.bodyData.remove(val.intValue());
targetLayer.fireLayerEvent(new RowDeleteEvent(targetLayer, val.intValue()));
}
return true;
}
return false;
}
}
and the Command will be triggered on clicking a MenuItem
this.contextMenu = new PopupMenuBuilder(natTable)
.withInspectLabelsMenuItem()
.withClearAllFilters()
.withColumnRenameDialog()
.withMenuItemProvider(new IMenuItemProvider() {
#Override
public void addMenuItem(final NatTable natTable, Menu popupMenu) {
MenuItem deleteRow = new MenuItem(popupMenu, SWT.PUSH);
deleteRow.setText("Delete Row(s)");
deleteRow.setEnabled(true);
deleteRow.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent event) {
//int rowPosition = MenuItemProviders.getNatEventData(event).getRowPosition();
ILayer bl = ((GridLayer)natTable.getLayer()).getBodyLayer();
BodyLayerStack bl1 = (BodyLayerStack) bl;
SelectionLayer sl = bl1.getSelectionLayer();
int []poss = new int[sl.getFullySelectedRowPositions().length];
int i=0;
for(int pos1 : sl.getFullySelectedRowPositions()){
poss[i]=sl.getRowIndexByPosition(pos1);
i++;
}
//System.out.println("Menu item selected "+rowPosition);
//natTable.doCommand(new DeleteRowCommand(natTable, rowPosition));
natTable.doCommand(new DeleteMultiRowCommand(natTable, poss));
}
});
}
})
.build();
when I try to delete the rows, rows which not selected are deleted. Seems like an issue with the row postion to row index conversion. is the row postion to row index conversion correct within my IMenuItemProvider right ?
It seems like you do the conversion from position to index twice: once in the menu item selection listener and once in the command handler (by calling convertToTargetLayer). The first is not necessary.
That is not an issue of NatTable, but an issue on how to work with collections. You need to remove the items backwards if you remove the elements one by one. Otherwise the items for the indexes are changing while processing.
Let's assume you want to delete the elements at index 1 and 2. After removing the element at index 1, the elements below will move up. So the element that was before on index 2 will be on index 1 now, and the element at index 3 will be on index 2. Therefore the removal of the element at index 2 in the next iteration will remove the item that was before on index 3.
I'd suggest to sort and reverse the collection of indexes before iterating to remove items from the collection. Than it should work.

How to style specific cells in CellTable depending the value of that cell (GWT)?

Ok, i have a CellTable that has 3 columns and 2 rows. I want the text in SOME specific cells (not all cell) in the table to be BOLD.
Please look at this code:
ListDataProvider<List<String>> dataProvider = new ListDataProvider<List<String>>();
dataProvider.addDataDisplay(table);
List<List<String>> list = dataProvider.getList();
List<String> sublist1= Arrays.asList("223","546","698");
List<String> sublist2= Arrays.asList("123","876","898");
List<String> sublist2= Arrays.asList("123","896","438");
IndexedColumn column1=new IndexedColumn(0);
table.addColumn(column1, "Col1");
IndexedColumn column2=new IndexedColumn(1);
table.addColumn(column2, "Col2");
IndexedColumn column3=new IndexedColumn(2);
table.addColumn(column3, "Col3");
Now, I want the Cell that is the intersect of row2 & col3 (ie "898") to be BOLD, so if i do like this
column3.setCellStyleNames(getView().getRes().css().myBoldColor());
Then it will make the whole column BOLD.
So, i think properly we need to loop over each cell in column3 & set the style accordingly, so that we can have the result like this:
Col1 - Col2 - Col3
223 - 546 - 698
123 - 876 - 898
123 - 896 - 438
You can try it be extending AbstractCell also.
Read here about Implementing the render() Method.
Sample code:
static class BoldCell extends AbstractCell<String> {
/**
* The HTML templates used to render the cell.
*/
interface Templates extends SafeHtmlTemplates {
#SafeHtmlTemplates.Template("<div style=\"{0}\">{1}</div>")
SafeHtml cell(SafeStyles styles, SafeHtml value);
}
/**
* Create a singleton instance of the templates used to render the cell.
*/
private static Templates templates = GWT.create(Templates.class);
#Override
public void render(Context context, String value, SafeHtmlBuilder sb) {
/*
* Always do a null check on the value. Cell widgets can pass null to cells if the
* underlying data contains a null, or if the data arrives out of order.
*/
if (value == null) {
return;
}
// If the value comes from the user, we escape it to avoid XSS attacks.
SafeHtml safeValue = SafeHtmlUtils.fromString(value);
// Use the template to create the Cell's html.
FontWeight weight = FontWeight.NORMAL;
if (safeValue.asString().equals("898")) {
weight = FontWeight.BOLD;
}
SafeStyles styles = SafeStylesUtils.forFontWeight(weight);
SafeHtml rendered = templates.cell(styles, safeValue);
sb.append(rendered);
}
}
In above code you can try it with row no also (Bold value for 0th column of 3rd row)
...
FontWeight weight = FontWeight.NORMAL;
if (context.getIndex()==2) {
weight = FontWeight.BOLD;
}
...
Cell<String> cell = new BoldCell();
Column<Contact, String> nameColumn = new Column<Contact, String>(cell) {
#Override
public String getValue(Contact object) {
return object.name;
}
};
table.addColumn(nameColumn, "Name");
Override getCellStyleNames() for a column:
Column<Document, Date> dueColumn = new Column<Document, Date>(new DateCell(DateTimeFormat.getFormat(PredefinedFormat.MONTH_ABBR_DAY))) {
#Override
public Date getValue(Document document) {
return document.getDueDate();
}
#Override
public String getCellStyleNames(Context context, Document document) {
if (document.getDueDate().getTime() < new Date().getTime()) {
return "boldStyle";
}
};

GWT DataGrid setEmptyTableWidget, no results, and no horizontal scollbars when more columns than current window will display

I'm using a DataGrid in one of my layouts. I have successfully specified some static text to display when there are no results using setEmptyTableWidget(Widget). Usually, I pass something like new HTML("No results").
But... when I have more columns than I can fit within the view port (i.e., current display width of browser window), I do not see all column headers, nor can I scroll to (the right to) view them.
I have a layout that supports scrolling when there IS data! But the horizontal scrollbar DOES NOT appear when there is no data. I cannot see my way out of this problem.
Any hints or suggestions are welcomed.
Here's my layout... (you will see where I call setEmptyTableWidget in PagingDataTableDatGrid#initGrid(DataGridConfiguration)'s method implementation below).
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:gwt="urn:import:com.google.gwt.user.client.ui"
xmlns:com="urn:import:org.spp.im.mui.gwt.client.module.common.widget.grid">
<ui:with field="res" type="org.spp.im.mui.gwt.client.resources.UiResources" />
<ui:with field="msg" type="org.spp.im.mui.gwt.shared.i18n.UiMessages" />
<!-- Layout -->
<gwt:DockLayoutPanel width="100%" height="100%" styleName="{res.style.container}" unit="PX">
<gwt:north size="25">
<gwt:HorizontalPanel width="100%">
<!-- Buttons -->
<gwt:cell horizontalAlignment="ALIGN_RIGHT">
<com:GridButtonBar ui:field="bar" />
</gwt:cell>
</gwt:HorizontalPanel>
</gwt:north>
<gwt:center>
<!-- Grid -->
<com:ReadOnlyGrid ui:field="grid" width="100%" />
</gwt:center>
<gwt:south size="25">
<gwt:HorizontalPanel width="100%">
<!-- Pagination controls -->
<gwt:cell horizontalAlignment="ALIGN_LEFT">
<com:CustomPager ui:field="pager" width="225px" />
</gwt:cell>
</gwt:HorizontalPanel>
</gwt:south>
</gwt:DockLayoutPanel>
</ui:UiBinder>
ReadOnlyGrid is a custom implementation...
public class ReadOnlyGrid extends PagingDataTableDataGrid<DataRow> {
private Set<Column<DataRow, ?>> columns = new HashSet<Column<DataRow, ?>>();
// preferred constructor in most cases
public ReadOnlyGrid() {
super();
}
public ReadOnlyGrid(final DataGridConfiguration config) {
super(config);
}
#Override
protected Set<Column<DataRow, ?>> allColumns() {
return columns;
}
#Override
// first column always has default ascending sort order
public void initTableColumns(final DataGrid<DataRow> dataGrid, final DataTable table,
final ListHandler<DataRow> sortHandler) {
Column<DataRow, String> column;
final int totalColumns = table.getColumnCount();
String columnName = null;
ColumnHints columnHints = null;
for (int col = 0; col < totalColumns; col++) {
final int c = col;
columnName = table.getColumnName(c);
columnHints = table.getColumnHints(columnName);
if (columnHints.isVisible()) {
column = new Column<DataRow, String>(new DataTableCell()) {
#Override
public String getValue(final DataRow row) {
String result = "";
if (row != null) {
result = row.get(c);
}
return result;
}
};
column.setSortable(true);
sortHandler.setComparator(column, new Comparator<DataRow>() {
#Override
public int compare(final DataRow r1, final DataRow r2) {
final String one = r1.get(c);
final String two = r2.get(c);
if (one == null ^ two == null) {
return one == null ? -1 : 1;
}
if (one == null && two == null) {
return 0;
}
return one.compareToIgnoreCase(two);
}
});
final String header = columnHints.getColumnHeader() == null ? columnName : columnHints.getColumnHeader();
// create the column header
// header should have the same alignment as the column data
dataGrid.addColumn(column, createHeader(header, columnHints.getColumnAlignment()));
// keep track of columns added
allColumns().add(column);
// Set the column width
dataGrid.setColumnWidth(column, columnHints.getColumnWidth(), Unit.PX);
// Set the column alignment
if (columnHints.getColumnAlignment() != null) {
column.setHorizontalAlignment(columnHints.getColumnAlignment());
}
else {
column.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT);//default
}
if (c == 0) {
dataGrid.getColumnSortList().push(column);
}
}
}
}
#Override
protected void initTableRows(final DataTable table) {
setDataList(table.allRows());
}
private SafeHtml createHeader(final String columnHeaderHtml, HasHorizontalAlignment.HorizontalAlignmentConstant columnHeaderAlignment) {
columnHeaderAlignment = columnHeaderAlignment == null ? HasHorizontalAlignment.ALIGN_RIGHT : columnHeaderAlignment;
final String ch = replaceCrWithBr(columnHeaderHtml);
final SafeHtmlBuilder sb = new SafeHtmlBuilder();
sb.appendHtmlConstant("<div align=\"" + columnHeaderAlignment.getTextAlignString() + "\">")
.appendHtmlConstant(ch).appendHtmlConstant("</div>");
final SafeHtml header = sb.toSafeHtml();
return header;
}
private String replaceCrWithBr(final String value) {
String result = value;
if (value.contains(App.INSTANCE.carriage_return())) {
result = value.replace(App.INSTANCE.carriage_return(), App.INSTANCE.separator());
}
return result;
}
}
And PagingDataTableDataGrid...
public abstract class PagingDataTableDataGrid<T extends DataRow> extends Composite {
private DataGrid<T> dataGrid;
private ListDataProvider<T> dataProvider;
private ResizeLayoutPanel wrapper;
// default, use in UiBinder template when you just want to #UiField inject a subclass
public PagingDataTableDataGrid() {
this(new DefaultDataGridConfiguration());
}
// alternate, use in UiBinder template when you want to create an instance
// yourself, user to inject w/ #UiField(provided=true)
public PagingDataTableDataGrid(final DataGridConfiguration config) {
wrapper = new ResizeLayoutPanel();
wrapper.setWidth("100%");
wrapper.setStyleName(UiResources.INSTANCE.style().gridWrapper());
initWidget(wrapper);
initGrid(config);
}
private void initGrid(final DataGridConfiguration config) {
dataGrid = new DataGrid<T>(config.getPageSize(), config.getResources());
final HTML noResults = new HTML(UiMessages.INSTANCE.no_results());
dataGrid.setEmptyTableWidget(noResults);
wrapper.clear();
wrapper.add(dataGrid);
}
public void setInput(final DataTable table) {
resetTableColumns();
dataProvider = new ListDataProvider<T>();
dataProvider.setList(new ArrayList<T>());
final ListHandler<T> sortHandler = new ListHandler<T>(dataProvider.getList());
dataGrid.addColumnSortHandler(sortHandler);
initTableColumns(dataGrid, table, sortHandler);
initTableRows(table);
dataProvider.addDataDisplay(dataGrid);
// trigger sort client-side
ColumnSortEvent.fire(dataGrid, dataGrid.getColumnSortList());
GridUtil.setStyles(this.dataGrid);
}
protected abstract Set<Column<T, ?>> allColumns();
// see
// http://stackoverflow.com/questions/3772480/remove-all-columns-from-a-celltable
// concrete classes are forced to maintain a handle on all columns added
private void resetTableColumns() {
for (final Column<T, ?> column : allColumns()) {
dataGrid.removeColumn(column);
}
allColumns().clear();
}
/**
* Add columns to this grid
*
* #param dataGrid
* a GWT DataGrid implementation
* #param table
* the model data
* #param sortHandler
* a GWT ListHandler implementation
*/
protected abstract void initTableColumns(DataGrid<T> dataGrid, DataTable table, ListHandler<T> sortHandler);
/**
* Add rows to this grid
* #param table the model data
*/
protected abstract void initTableRows(DataTable table);
protected void setDataList(final List<T> dataList) {
final List<T> list = dataProvider.getList();
list.addAll(dataList);
dataProvider.refresh();
}
public DataGrid<T> getDataGrid() {
return dataGrid;
}
}
So, as a "hack" I managed to get the behavior I wanted by using an insanely large pixel value for the width of the Widget.
E.g.,
Label noResults = new Label("No results");
noResults.setWidth("20000px");
This has the effect of pushing the text of the label all the way to the left, instead of it being centered underneath the column headers. But I can live w/ that, b/c the column headers are then scrollable.
There is nothing wrong with your code. It is as designed by the gwt. Why should a scroll appear if there is no data. Even I had similar doubt when working with datagrid but seriously it doesn't make sense to provide scroll when there is no data.

Adding a row-number column to GWT CellTable

I need to insert a new first-column into a CellTable, and display the RowNumber of the current row in it. What is the best way to do this in GWT?
Get the index of the element from the list wrapped by your ListDataProvider. Like this:
final CellTable<Row> table = new CellTable<Row>();
final ListDataProvider<Row> dataProvider = new ListDataProvider<Starter.Row>(getList());
dataProvider.addDataDisplay(table);
TextColumn<Row> numColumn = new TextColumn<Starter.Row>() {
#Override
public String getValue(Row object) {
return Integer.toString(dataProvider.getList().indexOf(object) + 1);
}
};
See here for the rest of the example.
Solution from z00bs is wrong, because row number calculating from object's index in data List. For example, for List of Strings with elements: ["Str1", "Str2", "Str2"], the row numbers will be [1, 2, 2]. It is wrong.
This solution uses the index of row in celltable for row number.
public class RowNumberColumn extends Column {
public RowNumberColumn() {
super(new AbstractCell() {
#Override
public void render(Context context, Object o, SafeHtmlBuilder safeHtmlBuilder) {
safeHtmlBuilder.append(context.getIndex() + 1);
}
});
}
#Override
public String getValue(Object s) {
return null;
}
}
and
cellTable.addColumn(new RowNumberColumn());

How do I add items to GWT ListBox in Uibinder .ui.xml template ?

How to add the listbox items using UiBinder?
It is possible since february 2011 version:
http://code.google.com/p/google-web-toolkit/issues/detail?id=4654
Following this patch you are now able to add items following this syntax:
<g:ListBox>
<g:item value='1'>
first item
</g:item>
<g:item value='2'>
second item
</g:item>
</g:ListBox>
This is a listbox of translations of an enumeration, I suppose this also works for a listbox with string values (version of GWT: 2.1.0)
You only need the renderer for translating the enumeration values.
//UI XML
<g:ValueListBox ui:field="requesterType"/>
//JAVA CODE
#UiField(provided = true)
ValueListBox<RequesterType> requesterType = new ValueListBox<RequesterType>(requesterTypeRenderer);
static EnumRenderer<RequesterType> requesterTypeRenderer = new EnumRenderer<RequesterType>();
public Constructor() {
requesterTypeRenderer.setEmptyValue(Translations.translateEmptyValue(RequesterType.class));
requesterType.setAcceptableValues(Arrays.asList(EnumUtil.getRequesterTypes()));
}
/**
* Translates enum entries. Use setEmptyValue() if you want to have a custom empty value. Default empty value is "".
*
* #param <T>
* an enumeration entry which is to be registered in {#link Translations}
*/
public class EnumRenderer<T extends Enum<?>> extends AbstractRenderer<T> {
private String emptyValue = "";
#Override
public String render(T object) {
if (object == null)
return emptyValue;
return Translations.translate(object);
}
public void setEmptyValue(String emptyValue) {
this.emptyValue = emptyValue;
}
}
GWT ValueListbox otherwise know as a ComboBox or Dropdown component.
Another example that also demonstrates populating the list.
UiBinder...
<g:ValueListBox ui:field="subCategory"/>
Editor...
#UiField(provided = true)
ValueListBox<String> subCategory = new ValueListBox<String>(
new Renderer<String>() {
#Override
public String render(String object) {
String s = "Cats";
if (object != null) {
s = object.toString();
}
return s;
}
#Override
public void render(String object, Appendable appendable)
throws IOException {
render(object);
}
});
Constructor...
List<String> values = new ArrayList<String>();
values.add("Animal Shelters and Rescues");
values.add("Birds");
values.add("Cats");
values.add("Dogs");
values.add("Other Pets");
values.add("Rabbits");
subCategory.setAcceptableValues(values);