---
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)
class Person {
    String name;
    int    age;
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public Integer getAge() {
        return age;
    }
    
    public void setAge(Integer age) {
        this.age = age.intValue();
    }
}

// Create an instance of the bean
Person bean = new Person();
        
// Wrap it in a BeanItem
BeanItem<Person> item = new BeanItem<Person>(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<Planet> item = new BeanItem<Planet>(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<Person>(planet.getDiscoverer(),
                                "born"));
----

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
<<dummy/../../../framework/datamodel/datamodel-container#datamodel.container.beancontainer.nestedproperties,"Nested
Properties">>.





