ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 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