ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 01.01.2026
Просмотров: 2621
Скачиваний: 0
Binding Components to Data
9.5. Collecting Items in Containers
The Container interface is the highest containment level of the Vaadin data model, for containing items (rows) which in turn contain properties (columns). Containers can therefore represent tabular data, which can be viewed in a Table or some other selection component, as well as hierarchical data.
The items contained in a container are identified by an item identifier or IID, and the properties by a property identifier or PID.
9.5.1. Basic Use of Containers
The basic use of containers involves creating one, adding items to it, and binding it as a container data source of a component.
Default Containers and Delegation
Before saying anything about creation of containers, it should be noted that all components that can be bound to a container data source are by default bound to a default container. For example,
Table is bound to a IndexedContainer, Tree to a HierarchicalContainer, and so forth.
All of the user interface components using containers also implement the relevant container interfaces themselves, so that the access to the underlying data source is delegated through the component.
//Create a table with one column Table table = new Table("My Table");
table.addContainerProperty("col1", String.class, null);
//Access items and properties through the component table.addItem("row1"); // Create item by explicit ID Item item1 = table.getItem("row1");
Property property1 = table.getItemProperty("col1"); property1.setValue("some given value");
//Equivant access through the container
Container container = table.getContainerDataSource(); container.addItem("row2");
Item item2 = container.getItem("row2");
Property property2 = table.getItemProperty("col1"); property2.setValue("another given value");
Creating and Binding a Container
A container is created and bound to a component as follows:
// Create a container
Container container = new IndexedContainer();
// Define the properties (columns) if required by container container.addContainerProperty("name", String.class, "none"); container.addContainerProperty("volume", Double.class, 0.0);
... add items ...
// Bind it to a component
Table table = new Table("My Table"); table.setContainerDataSource(container);
254 |
Collecting Items in Containers |
Binding Components to Data
Most components also allow passing the container in the constructor. Creation depends on the container type. For some containers, such as the IndexedContainer, you need to define the contained properties (columns) as was done above, while some others determine them otherwise. The definition of a property with addContainerProperty() requires a unique property ID, type, and a default value. You can also give null.
Vaadin has a several built-in in-memory container implementations, such as IndexedContainer and BeanItemContainer, which are easy to use for setting up nonpersistent data storages. For persistent data, either the built-in SQLContainer or the JPAContainer add-on container can be used.
Adding Items and Accessing Properties
Items can be added to a container with the addItem() method. The parameterless version of the method automatically generates the item ID.
// Create an item
Object itemId = container.addItem();
Properties can be requested from container by first requesting an item with getItem() and then getting the properties from the item with getItemProperty().
// Get the item object
Item item = container.getItem(itemId);
//Access a property in the item Property<String> nameProperty =
item.getItemProperty("name");
//Do something with the property nameProperty.setValue("box");
You can also get a property directly by the item and property ids with getContainerProperty().
container.getContainerProperty(itemId, "volume").setValue(5.0);
Adding Items by Given ID
Some containers, such as IndexedContainer and HierarchicalContainer, allow adding items by a given ID, which can be any Object.
Item item = container.addItem("agivenid"); item.getItemProperty("name").setValue("barrel"); Item.getItemProperty("volume").setValue(119.2);
Notice that the actual item is not given as a parameter to the method, only its ID, as the interface assumes that the container itself creates all the items it contains. Some container implementations can provide methods to add externally created items, and they can even assume that the item ID object is also the item itself. Lazy containers might not create the item immediately, but lazily when it is accessed by its ID.
9.5.2. Container Subinterfaces
The Container interface contains inner interfaces that container implementations can implement to fulfill different features required by components that present container data.
Container Subinterfaces |
255 |
Binding Components to Data
Container.Filterable
Filterable containers allow filtering the contained items by filters, as described in Section 9.5.7, “Filterable Containers”.
Container.Hierarchical
Hierarchical containers allow representing hierarchical relationships between items and are required by the Tree and TreeTable components.The HierarchicalContainer is a built-in in-memory container for hierarchical data, and is used as the default container for the tree components.The FilesystemContainer provides access to browsing the content of a file system. Also JPAContainer is hierarchical, as described in Section 21.4.4, “Hierarchical Container”.
Container.Indexed
An indexed container allows accessing items by an index number, not just their item ID. This feature is required by some components, especially Table, which needs to provide lazy access to large containers. The IndexedContainer is a basic in-memory implementation, as described in Section 9.5.3, “IndexedContainer”.
Container.Ordered
An ordered container allows traversing the items in successive order in either direction. Most built-in containers are ordered.
Container.SimpleFilterable
This interface enables filtering a container by string matching with addContainerFilter(). The filtering is done by either searching the given string anywhere in a property value, or as its prefix.
Container.Sortable
A sortable container is required by some components that allow sorting the content, such as Table, where the user can click a column header to sort the table by the column. Some other components, such as Calendar, may require that the content is sorted to be able to display it properly. Depending on the implementation, sorting can be done only when the sort() method is called, or the container is automatically kept in order according to the last call of the method.
See the API documentation for a detailed description of the interfaces.
9.5.3. IndexedContainer
The IndexedContainer is an in-memory container that implements the Indexed interface to allow referencing the items by an index. IndexedContainer is used as the default container in most selection components in Vaadin.
The properties need to be defined with addContainerProperty(), which takes the property ID, type, and a default value. This must be done before any items are added to the container.
// Create the container
IndexedContainer container = new IndexedContainer();
//Define the properties (columns) container.addContainerProperty("name", String.class, "noname"); container.addContainerProperty("volume", Double.class, -1.0d);
//Add some items
Object content[][] = {{"jar", 2.0}, {"bottle", 0.75}, {"can", 1.5}};
for (Object[] row: content) {
256 |
IndexedContainer |
Binding Components to Data
Item newItem = container.getItem(container.addItem()); newItem.getItemProperty("name").setValue(row[0]); newItem.getItemProperty("volume").setValue(row[1]);
}
New items are added with addItem(), which returns the item ID of the new item, or by giving the item ID as a parameter as was described earlier. Note that the Table component, which has IndexedContainer as its default container, has a conveniency addItem() method that allows adding items as object vectors containing the property values.
The container implements the Container.Indexed feature to allow accessing the item IDs by their index number, with getIdByIndex(), etc. The feature is required mainly for internal purposes of some components, such as Table, which uses it to enable lazy transmission of table data to the client-side.
9.5.4. BeanContainer
The BeanContainer is an in-memory container for JavaBean objects. Each contained bean is wrapped inside a BeanItem wrapper. The item properties are determined automatically by inspecting the getter and setter methods of the class. This requires that the bean class has public visibility, local classes for example are not allowed. Only beans of the same type can be added to the container.
The generic has two parameters: a bean type and an item identifier type. The item identifiers can be obtained by defining a custom resolver, using a specific item property for the IDs, or by giving item IDs explicitly. As such, it is more general than the BeanItemContainer, which uses the bean object itself as the item identifier, making the use usually simpler. Managing the item IDs makes BeanContainer more complex to use, but it is necessary in some cases where the equals() or hashCode() methods have been reimplemented in the bean.
// Here is a JavaBean
public class Bean implements Serializable { String name;
double energy; // Energy content in kJ/100g
public Bean(String name, double energy) { this.name = name;
this.energy = energy;
}
public String getName() { return name;
}
public void setName(String name) { this.name = name;
}
public double getEnergy() { return energy;
}
public void setEnergy(double energy) { this.energy = energy;
}
}
void basic(VerticalLayout layout) {
//Create a container for such beans with
//strings as item IDs. BeanContainer<String, Bean> beans =
BeanContainer |
257 |
Binding Components to Data
new BeanContainer<String, Bean>(Bean.class);
//Use the name property as the item ID of the bean beans.setBeanIdProperty("name");
//Add some beans to it
beans.addBean(new |
Bean("Mung bean", |
1452.0)); |
beans.addBean(new |
Bean("Chickpea", |
686.0)); |
beans.addBean(new |
Bean("Lentil", |
1477.0)); |
beans.addBean(new |
Bean("Common bean", |
129.0)); |
beans.addBean(new |
Bean("Soybean", |
1866.0)); |
// Bind a table to it |
|
|
Table table = new |
Table("Beans of All |
Sorts", beans); |
layout.addComponent(table); |
|
|
}
To use explicit item IDs, use the methods addItem(Object, Object), addItemAfter(Object, Object, Object), and addItemAt(int, Object, Object).
It is not possible to add additional properties to the container, except properties in a nested bean.
Nested Properties
If you have a nested bean with a 1:1 relationship inside a bean type contained in a BeanContainer or BeanItemContainer, you can add its properties to the container by specifying them with addNestedContainerProperty(). The feature is defined at the level of AbstractBeanContainer.
As with a top-level bean in a bean container, also a nested bean must have public visibility or otherwise an access exception is thrown. Intermediary getters returning a nested bean must always return a non-null value.
For example, assume that we have the following two beans with the first one nested inside the second one.
/** Bean to be nested */
public class EqCoord implements Serializable {
double |
rightAscension; |
/* |
In |
angle hours */ |
|
double |
declination; |
/* |
In |
degrees |
*/ |
... constructor and setters and getters for the properties ...
}
/** Bean containing a nested bean */
public class Star implements Serializable { String name;
EqCoord equatorial; /* Nested bean */
... constructor and setters and getters for the properties ...
}
After creating the container, you can declare the nested properties by specifying their property identifiers with the addNestedContainerProperty() in dot notation.
//Create a container for beans
final BeanItemContainer<Star> stars =
new BeanItemContainer<Star>(Star.class);
//Declare the nested properties to be used in the container stars.addNestedContainerProperty("equatorial.rightAscension"); stars.addNestedContainerProperty("equatorial.declination");
258 |
BeanContainer |