|
The The data contained in a When creating a table, you first need to define columns with /* Create the table with a caption. */
Table table = new Table("This is my Table");
/* Define the names and data types of columns.
* The "default value" parameter is meaningless here. */
table.addContainerProperty("First Name", String.class, null);
table.addContainerProperty("Last Name", String.class, null);
table.addContainerProperty("Year", Integer.class, null);
/* Add a few items in the table. */
table.addItem(new Object[] {
"Nicolaus","Copernicus",new Integer(1473)}, new Integer(1));
table.addItem(new Object[] {
"Tycho", "Brahe", new Integer(1546)}, new Integer(2));
table.addItem(new Object[] {
"Giordano","Bruno", new Integer(1548)}, new Integer(3));
table.addItem(new Object[] {
"Galileo", "Galilei", new Integer(1564)}, new Integer(4));
table.addItem(new Object[] {
"Johannes","Kepler", new Integer(1571)}, new Integer(5));
table.addItem(new Object[] {
"Isaac", "Newton", new Integer(1643)}, new Integer(6)); In this example, we used an increasing Scalability of the The The following example shows how to enable the selection of items in a // Allow selecting items from the table.
table.setSelectable(true);
// Send changes in selection immediately to server.
table.setImmediate(true);
// Shows feedback from selection.
final Label current = new Label("Selected: -");
// Handle selection change.
table.addListener(new Property.ValueChangeListener() {
public void valueChange(ValueChangeEvent event) {
current.setValue("Selected: " + table.getValue());
}
}); If the user clicks on an already selected item, the selection will deselected and the table property will have A table can also be in multiselect mode, where a user can select and unselect any item by clicking on it. The mode is enabled with the
Styling the overall style of a .v-table {}
.v-table-header-wrap {}
.v-table-header {}
.v-table-header-cell {}
.v-table-resizer {} /* Column resizer handle. */
.v-table-caption-container {}
.v-table-body {}
.v-table-row-spacer {}
.v-table-table {}
.v-table-row {}
.v-table-cell-content {} Notice that some of the widths and heights in a table are calculated dynamically and can not be set in CSS. The Alternatively, you can use a Table.ColumnGenerator (see Section 5.12.4, “Generated Table Columns”) to generate the actual UI components of the cells and add style names to them. A cell style generator is not used for the cells in generated columns. Table table = new Table("Table with Cell Styles");
table.addStyleName("checkerboard");
// Add some columns in the table. In this example, the property
// IDs of the container are integers so we can determine the
// column number easily.
table.addContainerProperty("0", String.class, null, "", null, null);
for (int i=0; i<8; i++)
table.addContainerProperty(""+(i+1), String.class, null,
String.valueOf((char) (65+i)), null, null);
// Add some items in the table.
table.addItem(new Object[]{
"1", "R", "N", "B", "Q", "K", "B", "N", "R"}, new Integer(0));
table.addItem(new Object[]{
"2", "P", "P", "P", "P", "P", "P", "P", "P"}, new Integer(1));
for (int i=2; i<6; i++)
table.addItem(new Object[]{String.valueOf(i+1),
"", "", "", "", "", "", "", ""}, new Integer(i));
table.addItem(new Object[]{
"7", "P", "P", "P", "P", "P", "P", "P", "P"}, new Integer(6));
table.addItem(new Object[]{
"8", "R", "N", "B", "Q", "K", "B", "N", "R"}, new Integer(7));
table.setPageLength(8);
// Set cell style generator
table.setCellStyleGenerator(new Table.CellStyleGenerator() {
public String getStyle(Object itemId, Object propertyId) {
int row = ((Integer)itemId).intValue();
int col = Integer.parseInt((String)propertyId);
// The first column.
if (col == 0)
return "rowheader";
// Other cells.
if ((row+col)%2 == 0)
return "black";
else
return "white";
}
}); You can then style the cells, for example, as follows: /* Center the text in header. */
.v-table-header-cell {
text-align: center;
}
/* Basic style for all cells. */
.v-table-checkerboard .v-table-cell-content {
text-align: center;
vertical-align: middle;
padding-top: 12px;
width: 20px;
height: 28px;
}
/* Style specifically for the row header cells. */
.v-table-cell-content-rowheader {
background: #E7EDF3
url(../default/table/img/header-bg.png) repeat-x scroll 0 0;
}
/* Style specifically for the "white" cells. */
.v-table-cell-content-white {
background: white;
color: black;
}
/* Style specifically for the "black" cells. */
.v-table-cell-content-black {
background: black;
color: white;
} The table will look as shown in Figure 5.34, “Cell Style Generator for a Table”. The default style for Setting the page length to zero makes all the rows in a table visible, no matter how many rows there are. Notice that this also effectively disables buffering, as all the entire table is loaded to the browser at once. Using such tables to generate reports does not scale up very well, as there is some inevitable overhead in rendering a table with Ajax. For very large reports, generating HTML directly is a more scalable solution. The default scrollable style supports most of the table features. User can resize the columns by dragging their borders, change the sorting by clicking on the column headers, collapse the columns if The cells of a When handling events for components inside a The example below includes table rows with a // Create a table and add a style to allow setting the row height in theme.
final Table table = new Table();
table.addStyleName("components-inside");
/* Define the names and data types of columns.
* The "default value" parameter is meaningless here. */
table.addContainerProperty("Sum", Label.class, null);
table.addContainerProperty("Is Transferred", CheckBox.class, null);
table.addContainerProperty("Comments", TextField.class, null);
table.addContainerProperty("Details", Button.class, null);
/* Add a few items in the table. */
for (int i=0; i<100; i++) {
// Create the fields for the current table row
Label sumField = new Label(String.format(
"Sum is <b>$%04.2f</b><br/><i>(VAT incl.)</i>",
new Object[] {new Double(Math.random()*1000)}),
Label.CONTENT_XHTML);
CheckBox transferredField = new CheckBox("is transferred");
// Multiline text field. This required modifying the
// height of the table row.
TextField commentsField = new TextField();
commentsField.setRows(3);
// The Table item identifier for the row.
Integer itemId = new Integer(i);
// Create a button and handle its click. A Button does not
// know the item it is contained in, so we have to store the
// item ID as user-defined data.
Button detailsField = new Button("show details");
detailsField.setData(itemId);
detailsField.addListener(new Button.ClickListener() {
public void buttonClick(ClickEvent event) {
// Get the item identifier from the user-defined data.
Integer itemId = (Integer)event.getButton().getData();
getWindow().showNotification("Link "+
itemId.intValue()+" clicked.");
}
});
detailsField.addStyleName("link");
// Create the table row.
table.addItem(new Object[] {sumField, transferredField,
commentsField, detailsField},
itemId);
}
// Show just three rows because they are so high.
table.setPageLength(3); The row height has to be set higher than the default with a style rule such as the following: /* Table rows contain three-row TextField components. */
.v-table-components-inside .v-table-cell-content {
height: 54px;
} The table will look as shown in Figure 5.35, “Components in a Table”. Normally, a Let us begin with a regular table with a some columns with usual Java types, namely a // Create a table. It is by default not editable.
final Table table = new Table();
// Define the names and data types of columns.
table.addContainerProperty("Date", Date.class, null);
table.addContainerProperty("Work", Boolean.class, null);
table.addContainerProperty("Comments", String.class, null);
// Add a few items in the table.
for (int i=0; i<100; i++) {
Calendar calendar = new GregorianCalendar(2008,0,1);
calendar.add(Calendar.DAY_OF_YEAR, i);
// Create the table row.
table.addItem(new Object[] {calendar.getTime(),
new Boolean(false),
""},
new Integer(i)); // Item identifier
}
table.setPageLength(8);
layout.addComponent(table); You could put the table in editable mode right away if you need to. We'll continue the example by adding a mechanism to switch the final CheckBox switchEditable = new CheckBox("Editable");
switchEditable.addListener(new Property.ValueChangeListener() {
public void valueChange(ValueChangeEvent event) {
table.setEditable(((Boolean)event.getProperty()
.getValue()).booleanValue());
}
});
switchEditable.setImmediate(true);
layout.addComponent(switchEditable); Now, when you check to checkbox, the components in the table turn into editable fields, as shown in Figure 5.36, “A Table in Normal and Editable Mode”. The field components that allow editing the values of particular types in a table are defined in a field factory that implements the Table 5.2. Type to Field Mappings in
Field factories are covered with more detail in Section 5.17.2, “Binding Form to Data”. You could just implement the As the items in a You might want to have a column that has values calculated from other columns. Or you might want to format table columns in some way, for example if you have columns that display currencies. The You add new generated columns to a // Define table columns.
table.addContainerProperty(
"date", Date.class, null, "Date", null, null);
table.addContainerProperty(
"quantity", Double.class, null, "Quantity (l)", null, null);
table.addContainerProperty(
"price", Double.class, null, "Price (e/l)", null, null);
table.addContainerProperty(
"total", Double.class, null, "Total (e)", null, null);
// Define the generated columns and their generators.
table.addGeneratedColumn("date",
new DateColumnGenerator());
table.addGeneratedColumn("quantity",
new ValueColumnGenerator("%.2f l"));
table.addGeneratedColumn("price",
new PriceColumnGenerator());
table.addGeneratedColumn("total",
new ValueColumnGenerator("%.2f e")); Notice that the table.setVisibleColumns(new Object[] {"date", "quantity", "price", "total"}); The generators are objects that implement the The following example defines a generator for formatting /** Formats the value in a column containing Double objects. */
class ValueColumnGenerator implements Table.ColumnGenerator {
String format; /* Format string for the Double values. */
/**
* Creates double value column formatter with the given
* format string.
*/
public ValueColumnGenerator(String format) {
this.format = format;
}
/**
* Generates the cell containing the Double value.
* The column is irrelevant in this use case.
*/
public Component generateCell(Table source, Object itemId,
Object columnId) {
// Get the object stored in the cell as a property
Property prop =
source.getItem(itemId).getItemProperty(columnId);
if (prop.getType().equals(Double.class)) {
Label label = new Label(String.format(format,
new Object[] { (Double) prop.getValue() }));
// Set styles for the column: one indicating that it's
// a value and a more specific one with the column
// name in it. This assumes that the column name
// is proper for CSS.
label.addStyleName("column-type-value");
label.addStyleName("column-" + (String) columnId);
return label;
}
return null;
}
}
The generator is called for all the visible (or more accurately cached) items in a table. If the user scrolls the table to another position in the table, the columns of the new visible rows are generated dynamically. The columns in the visible (cached) rows are also generated always when an item has a value change. It is therefore usually safe to calculate the value of generated cells from the values of different rows (items). When you set a table as // Have a check box that allows the user
// to make the quantity and total columns editable.
final CheckBox editable = new CheckBox(
"Edit the input values - calculated columns are regenerated");
editable.setImmediate(true);
editable.addListener(new ClickListener() {
public void buttonClick(ClickEvent event) {
table.setEditable(editable.booleanValue());
// The columns may not be generated when we want to
// have them editable.
if (editable.booleanValue()) {
table.removeGeneratedColumn("quantity");
table.removeGeneratedColumn("total");
} else { // Not editable
// Show the formatted values.
table.addGeneratedColumn("quantity",
new ValueColumnGenerator("%.2f l"));
table.addGeneratedColumn("total",
new ValueColumnGenerator("%.2f e"));
}
// The visible columns are affected by removal
// and addition of generated columns so we have
// to redefine them.
table.setVisibleColumns(new Object[] {"date", "quantity",
"price", "total", "consumption", "dailycost"});
}
});
You will also have to set the editing fields in
public class ImmediateFieldFactory extends DefaultFieldFactory {
public Field createField(Container container,
Object itemId,
Object propertyId,
Component uiContext) {
// Let the DefaultFieldFactory create the fields...
Field field = super.createField(container, itemId,
propertyId, uiContext);
// ...and just set them as immediate.
((AbstractField)field).setImmediate(true);
return field;
}
}
...
table.setFieldFactory(new ImmediateFieldFactory()); If you generate the editing fields with the column generator, you avoid having to use such a field factory, but of course have to generate the fields for both normal and editable modes. Figure 5.37, “Table with Generated Columns in Normal and Editable Mode” shows a table with columns calculated (blue) and simply formatted (black) with column generators. You can find the complete generated columns example in the Feature Browser demo application in the installation package, in |
Table of Contents
|