--- title: Holding properties in Items order: 3 layout: page --- [[datamodel.items]] = Holding properties in Items The [classname]#Item# interface provides access to a set of named properties. Each property is identified by a __property identifier__ (PID) and a reference to such a property can be queried from an [classname]#Item# with [methodname]#getItemProperty()# using the identifier. Examples on the use of items include rows in a [classname]#Table#, with the properties corresponding to table columns, nodes in a [classname]#Tree#, and the the data bound to a [classname]#Form#, with item's properties bound to individual form fields. Items are generally equivalent to objects in the object-oriented model, but with the exception that they are configurable and provide an event handling mechanism. The simplest way to utilize [classname]#Item# interface is to use existing implementations. Provided utility classes include a configurable property set ( [classname]#PropertysetItem#) and a bean-to-item adapter ( [classname]#BeanItem#). Also, a [classname]#Form# implements the interface and can therefore be used directly as an item. In addition to being used indirectly by many user interface components, items provide the basic data model underlying the [classname]#Form# component. In simple cases, forms can even be generated automatically from items. The properties of the item correspond to the fields of the form. The [classname]#Item# interface defines inner interfaces for maintaining the item property set and listening changes made to it. [classname]#PropertySetChangeEvent# events can be emitted by a class implementing the [classname]#PropertySetChangeNotifier# interface. They can be received through the [classname]#PropertySetChangeListener# interface. ifdef::web[] [[datamodel.items.propertysetitem]] == The [classname]#PropertysetItem# Implementation The [classname]#PropertysetItem# is a generic implementation of the [classname]#Item# interface that allows storing properties. The properties are added with [methodname]#addItemProperty()#, which takes a name and the property as parameters. The following example demonstrates a typical case of collecting [classname]#ObjectProperty# properties in an item: ---- PropertysetItem item = new PropertysetItem(); item.addItemProperty("name", new ObjectProperty("Zaphod")); item.addItemProperty("age", new ObjectProperty(42)); // Bind it to a component Form form = new Form(); form.setItemDataSource(item); ---- endif::web[] [[datamodel.items.beanitem]] == Wrapping a Bean in a [classname]#BeanItem# The [classname]#BeanItem# implementation of the [classname]#Item# interface is a wrapper for Java Bean objects. In fact, only the setters and getters are required while serialization and other bean features are not, so you can wrap almost any POJOs with minimal requirements. ---- // Here is a bean (or more exactly a POJO) public class Person { String name; int yearOfBirth; public Person(String name, int yearOfBirth) { this.name = name; this.yearOfBirth = yearOfBirth; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getYearOfBirth() { return yearOfBirth; } public void setYearOfBirth(int yearOfBirth) { this.yearOfBirth = yearOfBirth; } } // Create an instance of the bean Person bean = new Person(); // Wrap it in a BeanItem BeanItem item = new BeanItem(bean); // Bind it to a component Form form = new Form(); form.setItemDataSource(item); ---- You can use the [methodname]#getBean()# method to get a reference to the underlying bean. [[datamodel.items.beanitem.nested]] === Nested Beans You may often have composite classes where one class "has a" another class. For example, consider the following [classname]#Planet# class which "has a" discoverer: ---- // Here is a bean with two nested beans public class Planet implements Serializable { String name; Person discoverer; public Planet(String name, Person discoverer) { this.name = name; this.discoverer = discoverer; } ... getters and setters ... } ... // Create an instance of the bean Planet planet = new Planet("Uranus", new Person("William Herschel", 1738)); ---- When shown in a [classname]#Form#, for example, you would want to list the properties of the nested bean along the properties of the composite bean. You can do that by binding the properties of the nested bean individually with a [classname]#MethodProperty# or [classname]#NestedMethodProperty#. You should usually hide the nested bean from binding as a property by listing only the bound properties in the constructor. ---- // Wrap it in a BeanItem and hide the nested bean property BeanItem item = new BeanItem(planet, new String[]{"name"}); // Bind the nested properties. // Use NestedMethodProperty to bind using dot notation. item.addItemProperty("discoverername", new NestedMethodProperty(planet, "discoverer.name")); // The other way is to use regular MethodProperty. item.addItemProperty("discovererborn", new MethodProperty(planet.getDiscoverer(), "yearOfBirth")); ---- The difference is that [classname]#NestedMethodProperty# does not access the nested bean immediately but only when accessing the property values, while when using [classname]#MethodProperty# the nested bean is accessed when creating the method property. The difference is only significant if the nested bean can be null or be changed later. You can use such a bean item for example in a [classname]#Form# as follows: ---- // Bind it to a component Form form = new Form(); form.setItemDataSource(item); // Nicer captions form.getField("discoverername").setCaption("Discoverer"); form.getField("discovererborn").setCaption("Born"); ---- [[figure.datamodel.items.beanitem.nested]] .A [classname]#Form# with Nested Bean Properties image::img/beanitem-nested-beans.png[] The [classname]#BeanContainer# and [classname]#BeanItemContainer# allow easy definition of nested bean properties with [methodname]#addNestedContainerProperty()#, as described in <>.