-
Notifications
You must be signed in to change notification settings - Fork 9
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
ComponentConfigurators - each component group is configured with
ComponentGroupConfigurators - all components are configured as a single group (using the above
ComponentGroupConfigurators, but withnullas 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/areprefixes forbooleanandBoolean) - using single-
Propertygroups 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 ObjectFields (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:
-
FieldOrderdefines the order in which (Vaadin) fields are displayed -
FieldGroupspecifies groups -
FieldCaptionoverrides the default caption -
BigFieldon aStringproperty will result in a text area being shown, rather than a text field -
ComponentIdandComponentStyleallow setting id of and adding styles to the constructed (Vaadin) field, respectively -
ShowFieldAsoverrides the default (Vaadin) field with the provided one that must have a public, no-arg constructor -
BuildFieldWithhas 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) -
Stringis shown asSuperTextFieldorSuperTextArea -
LocalDateandLocalDateTimewith its correspondingSuper___Picker -
List<X>andSet<X>are shown with aCollectionFieldthat usesObjectField<X>for unknown types, and above types for everything else -
Map<K, V>is shown with aMapFieldwithObjectField<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
ObjectFields - 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,SetandMapare 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
FlexLayoyuts (columns for main layouts, rows for nested ones)