-
Notifications
You must be signed in to change notification settings - Fork 7
How to use ObjectField?
In short, ObjectField
is a (Vaadin) field of type T
that displays (Vaadin) fields for each Property
of that object. This happens in order:
- properties of the object are obtained with a
PropertyProvider
; if there are no changes in properties, existing (Vaadin) fields are reused - nothing else happens; - those properties are then grouped with a
PropertyGroupingProvider
, such that each group has a name; - for each group a layout is built using a
PropertyGroupLayoutProvider
; - each property in each group is mapped to a (Vaadin) field using
PropertyComponentBuilder
; - eachj field is then added to its group's layout (if the group does not have any layout, then the component is added to the
ObjectField
's main layout); - each component is configured with
ComponentConfigurator
s - each component group is configured with
ComponentGroupConfigurator
s - all components are configured as a single group (using the above
ComponentGroupConfigurator
s, but withnull
as the group name).
After all of the above is done, ObjectField
obtains a value for each Property
and then sets value of the corresponding (Vaadin) field.
The above mechanism allows modifying the ObjectField
in almost every way, except the order in which things happen. However, it comes at a significant price of steep learning curve.
Out-of-the-box ObjectField
is capable of displaying any object by:
- using reflection to inspect (Java) fields, their getters and setters (considering
is
/are
prefixes forboolean
andBoolean
) - using single-
Property
groups and no separate layouts (all components end up in the main layout) - using
LabelField
(withtoString
) as the default component for everything - using no configurators
To reuse common settings across different ObjectField
s (regardless of their type), use ObjectFieldFactory
. By itself it is configured to:
- use reflection to inspect (Java) fields, setters and getters and to collect various metadata based on annotations
- use metadata to group related properties (otherwise using one property per group)
- build components using best educated guess
- configure labels and read-only-ness based on metadata (default label being human-readable name of the
Property
) - assign each group and each component class names for easy styling
The following annotations can be used:
-
FieldOrder
defines the order in which (Vaadin) fields are displayed -
FieldGroup
specifies groups -
FieldCaption
overrides the default caption -
BigField
on aString
property will result in a text area being shown, rather than a text field -
ComponentId
andComponentStyle
allow setting id of and adding styles to the constructed (Vaadin) field, respectively -
ShowFieldAs
overrides the default (Vaadin) field with the provided one that must have a public, no-arg constructor -
BuildFieldWith
has the same effect asShowFieldAs
, but allows more control over the (Vaadin) field by using a builder (that must have a public, no-arg constructor)
The above annotations can be used on a (Java) field, a setter or a getter associated with the (Java) field. Associated means the name of the method follows Java naming pattern (SomeType field
-> setField(SomeType value)
and SomeType getField()
, with isField
and areField
also supported for boolean
and Boolean
types).
Note that technically the annotations are converted to metadata, and it is the presence of the metadata that defines what component is created, how it is configured, etc. So it is entirely possible to build a PropertyProvider
that obtains the same metadata through different means and still enjoy the benefits of ObjectFieldFactory
.
Again, there are some reasonable defaults:
- boolean properties are mapped to
Checkbox
- various number types are mapped to supported
Super___Field
(integer, long, double and BigDecimal) -
String
is shown asSuperTextField
orSuperTextArea
-
LocalDate
andLocalDateTime
with its correspondingSuper___Picker
-
List<X>
andSet<X>
are shown with aCollectionField
that usesObjectField<X>
for unknown types, and above types for everything else -
Map<K, V>
is shown with aMapField
withObjectField<X>
for unknown types, and above types for everything else
Note that in the above if creating an ObjectField
fails, it should be replaced with a LabelField
.
As with ObjectField
, the factory is highly configurable through its public
methods:
- layouts for collection, object and map fields
- style names for group layouts and components in groups inside
ObjectField
s - instance suppliers for objects and empty collections
In addition to the above, a number of protected
methods (like buildAndConfigurePropertyProvider
) can be overwritten in a subclass of ObjectFieldFactory
.
There are some limitations:
- objects are scanned via reflection
- creating objects by default is done by reflection, but can be overwritten by adding instance suppliers
- only
List
,Set
andMap
are supported; custom collection types can be added, but they must have its first generic attribute as the type that is contained in the collection - default layouts are all
FlexLayoyut
s (columns for main layouts, rows for nested ones)