Vaadin user interface components are built on a skeleton of interfaces and abstract classes that define and implement the features common to all components and the basic logic how the component states are serialized between the server and the client.
This section gives details on the basic component interfaces and abstractions. The layout and other component container abstractions are described in Chapter 6, Managing Layout. The interfaces that define the Vaadin data model are described in Chapter 9, Binding Components to Data.
All components also implement the Paintable
interface,
which is used for serializing ("painting") the components to the client, and
the reverse VariableOwner
interface, which is needed
for deserializing component state or user interaction from the client.
In addition to the interfaces defined within the Vaadin framework, all
components implement the java.io.Serializable
interface
to allow serialization. Serialization is needed in many clustering and cloud
computing solutions.
The Component
interface is paired with the
AbstractComponent
class, which implements all the
methods defined in the interface.
Components are laid out in the user interface hierarchically. The
layout is managed by layout components, or more generally components
that implement the ComponentContainer
interface. Such a container is the parent of the contained components.
The getParent()
method allows retrieving the
parent component of a component. While there is a
setParent()
, you rarely need it as you
usually add components with the
addComponent()
method of the
ComponentContainer
interface, which
automatically sets the parent.
A component does not know its parent when the component is created, so
you can not refer to the parent in the constructor with
getParent()
. Also, it is not possible to
fetch a reference to the application object with
getApplication()
before having a parent. For
example, the following is invalid:
public class AttachExample extends CustomComponent { public AttachExample() { // ERROR: We can't access the application object yet. ClassResource r = new ClassResource("smiley.jpg", getApplication()); Embedded image = new Embedded("Image:", r); setCompositionRoot(image); } }
Adding a component to an application triggers calling the
attach()
method for the
component. Correspondingly, removing a component from a container
triggers calling the detach()
method. If the
parent of an added component is already connected to the application,
the attach()
is called immediately from
setParent()
.
public class AttachExample extends CustomComponent { public AttachExample() { } @Override public void attach() { super.attach(); // Must call. // Now we know who ultimately owns us. ClassResource r = new ClassResource("smiley.jpg", getApplication()); Embedded image = new Embedded("Image:", r); setCompositionRoot(image); } }
The attachment logic is implemented in
AbstractComponent
, as described in Section 5.2.2, “AbstractComponent
”.
AbstractComponent
is the base class for all user
interface components. It is the (only) implementation of the
Component
interface, implementing all the methods
defined in the interface.
AbstractComponent
has a single abstract method,
getTag()
, which returns the serialization
identifier of a particular component class. It needs to be implemented
when (and only when) creating entirely new
components. AbstractComponent
manages much of the
serialization of component states between the client and the
server. Creation of new components and serialization is described in Chapter 11, Developing New Components, and the server-side serialization API in Appendix A, User Interface Definition Language (UIDL).
Fields are components that have a value that the user can change through the user interface. Figure 5.3, “Field Components” illustrates the inheritance relationships and the important interfaces and base classes.
Field components are built upon the framework defined in the
Field
interface and the
AbstractField
base class.
Fields are strongly coupled with the Vaadin data model. The field value is
handled as a Property
of the field
component. Selection fields allow management of the selectable items
through the Container
interface.
The description of the field interfaces and base classes is broken down in the following sections.
The Field
interface inherits the
Component
superinterface and also the
Property
interface to have a value for the
field. AbstractField
is the only class
implementing the Field
interface directly. The
relationships are illustrated in Figure 5.4, “Field
Interface Inheritance Diagram”.
You can set the field value with the setValue()
and read with the getValue()
method defined in
the Property
interface. The actual value type
depends on the component.
The Field
interface defines a number of
attributes, which you can retrieve or manipulate with the
corresponding setters and getters.
description
All fields have a description. Notice that while this
attribute is defined in the
Field
component, it is
implemented in AbstractField
,
which does not directly implement
Field
, but only through the
AbstractField
class.
required
When enabled, a required indicator (usually the asterisk *
character) is displayed on the left, above, or right the
field, depending on the containing layout and whether the
field has a caption. If such fields are validated but are
empty and the requiredError
property (see below) is set, an error indicator is shown
and the component error is set to the text defined with
the error property. Without validation, the required
indicator is merely a visual guide.
requiredError
Defines the error message to show when a value is
required, but none is entered. The error message is set as
the component error for the field and is usually displayed
in a tooltip when the mouse pointer hovers over the error
indicator. The Form
component can
display the error message in a special error indicator
area.
Field
inherits
Property.ValueChangeListener
to allow listening
for field value changes and Property.Editor
to
allow editing values.
When the value of a field changes, a
Property.ValueChangeEvent
is triggered for
the field. You should not implement the
valueChange()
method in a class
inheriting AbstractField
, as it is already
implemented in AbstractField
. You should
instead implement the method explicitly by adding the implementing
object as a listener.