# Holon Platform Vaadin Flow Module - Reference manual

version 5.2.13

Copyright © 2016-2019

Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically.

## 1. Introduction

The Vaadin Flow module provides integration between the Holon Platform architecture and the Vaadin Flow web applications platform.

The module main features are:

- A complete set of UI components fluent builders, to make the UI development fast and easy.

- A full integration with the Holon Platform Property model and Datastore API for data bound UI components.

- A complete support for UI components and messages localization, using the Holon Platform internationalization support.

- A convenient navigation API to manage the UI views, with typed parameters support and components lifecycle management.

- Integration with the Holon Platform authentication and authentication architecture.

- A complete integration with Spring and Spring Boot, with application auto-configuration facilities.

### 1.1. Sources and contributions

The Holon Platform Vaadin module source code is available from the GitHub repository https://github.com/holon-platform/holon-vaadin-flow.

See the repository `README` file for information about:

- The source code structure.

- How to build the module artifacts from sources.

- Where to find the code examples.

- How to contribute to the module development.

## 2. Obtaining the artifacts

The Holon Platform uses Maven for projects build and configuration. All the platform artifacts are published in the Maven Central Repository, so there is no need to explicitly declare additional repositories in your project `pom` file.

At the top of each section of this documentation you will find the Maven coordinates (group id, artifact id and version) to obtain the artifact(s) as a dependency for your project.

A BOM (Bill Of Materials) `pom` is provided to import the available dependencies for a specific version in your projects. The Maven coordinates for the core BOM are the following:

Maven coordinates:

    <groupId>com.holon-platform.vaadin</groupId>
    <artifactId>holon-vaadin-flow-bom</artifactId>
    <version>5.2.13</version>

The BOM can be imported in a Maven project in the following way:

    <dependencyManagement>
      <dependencies>
        <dependency>
          <groupId>com.holon-platform.vaadin</groupId>
          <artifactId>holon-vaadin-flow-bom</artifactId>
          <version>5.2.13</version>
          <type>pom</type>
          <scope>import</scope>
        </dependency>
      </dependencies>
    </dependencyManagement>

### 2.1. Using the Platform BOM

The Holon Platform provides an overall Maven BOM (Bill of Materials) to easily obtain all the available platform artifacts.

See Obtain the platform artifacts for details.

## 3. Vaadin Flow UI components

The `holon-vaadin-flow` artifact is the main entry point to enable the Holon platform Vaadin Flow integration.

Maven coordinates:

    <groupId>com.holon-platform.vaadin</groupId>
    <artifactId>holon-vaadin-flow</artifactId>
    <version>5.2.13</version>

It provides integration between the Vaadin Flow core architecture and the Holon Platform one, providing also a set of UI components specifically designed to ensure a seamless integration with the Holon Platform Property model, Datastore API, authentication and internationalization APIs.

### 3.1. Datastore API integration

The Holon Platform Datastore API can be used to bind a UI component to backend data in a simple and powerful way, relying on the Holon Platform Property model to represent the underlying data model.

The DatastoreDataProvider API is a standard Vaadin Flow `com.vaadin.flow.data.provider.DataProvider` which uses the `Datastore` API to fetch data from backend and makes available a set of configuration methods to control and setup the queries to perform.

Since it is a standard `DataProvider`, it can be seamlessy used in any Vaadin UI component which support data binding.

The `DatastoreDataProvider` provides a set of `create(..)` and `builder(..)` methods to build and configure a new `Datastore` based `DataProvider`. At least the following elements are required to create a `DatastoreDataProvider`:

- The reference to the `Datastore` instance to use.

- A `DataTarget` declaration, which represents the data model entity to use as data source (for example, a RDBMS table name).

#### 3.1.1. Item types

By default, the Holon Platform Property model is used to represent the backend data model attributes, and the PropertyBox type to represent a data source item, intended as a collection of properties and their values.

So, besides the `Datastore` reference and the `DataTarget` definition, the property set to use has to be provided to the `DatastoreDataProvider` builder methods.

    final NumericProperty<Long> ID = NumericProperty.longType("id");
    final StringProperty NAME = StringProperty.create("name");

    final PropertySet<?> SUBJECT = PropertySet.of(ID, NAME); (1)

    final DataTarget<?> TARGET = DataTarget.named("subjects"); (2)

    final Datastore datastore = obtainDatastore(); (3)

    DataProvider<PropertyBox, QueryFilter> dataProvider = DatastoreDataProvider.create(datastore, TARGET, SUBJECT); (4)

    dataProvider = DatastoreDataProvider.create(datastore, TARGET, ID, NAME); (5)

1 | Property set declaration
2 | Data target definition
3 | Datastore reference
4 | Create a new `DatastoreDataProvider` using the `SUBJECT` property set
5 | Create a new `DatastoreDataProvider` providing the `ID` and `NAME` properties as property set

Furthermore, the `DatastoreDataProvider` API provides methods to use a bean class as item type. The item property set is obtained form the bean class attributes, using the bean property names as property set property names.

| See the Java Beans and property model documentation section for information about the conventions and the configuration options which can be used when a Java Bean is used with the Holon Platform property model.

    final DataTarget<?> TARGET = DataTarget.named("subjects"); (1)

    final Datastore datastore = obtainDatastore(); (2)

    DataProvider<MyBean, QueryFilter> dataProvider = DatastoreDataProvider.create(datastore, TARGET, MyBean.class); (3)

1 | Data target definition
2 | Datastore reference
3 | Create a new `DatastoreDataProvider` using the `MyBean` class as item type

#### 3.1.2. Filter types

By default, the `QueryFilter` type is used used as data provider filter type, since it is the default property model representation for the `Datastore` API query restrictions definition.

To use a different data provider filter type, a filter converter function can be configured for the `DatastoreDataProvider`, to provide the custom filter type to `QueryFilter` type conversion logic.

In the example below, a `String` type filter is used and the conversion function creates a `QueryFilter` which represents the condition "The `NAME` data model attribute value starts with the given filter value":

    DataProvider<PropertyBox, String> dataProvider = DatastoreDataProvider.create(datastore, TARGET, SUBJECT,
        stringValue -> NAME.startsWith(stringValue));

Similarly when a bean item type is used:

    DataProvider<MyBean, String> dataProvider = DatastoreDataProvider.create(datastore, TARGET, MyBean.class,
        stringValue -> NAME.startsWith(stringValue));

#### 3.1.3. Custom item and filter type

The `DatastoreDataProvider` API makes also available methods to customize both the item type and the data provider filter type, providing:

- The `PropertyBox` type to the custom item type conversion function.

- The custom filter type to the `QueryFilter` type conversion function.

For example, using a `MyItem` item class and a `String` filter type:

    DataProvider<MyItem, String> dataProvider = DatastoreDataProvider.create(datastore, TARGET, //
        SUBJECT, (1)
        propertyBox -> new MyItem(propertyBox.getValue(ID), propertyBox.getValue(NAME)), (2)
        stringValue -> NAME.startsWith(stringValue)); (3)

1 | The `SUBJECT` property set is used as query projection
2 | Item conversion function: from the `PropertyBox` type object to the `MyItem` item type
3 | Filter conversion function: from a `String` type filter to a `QueryFilter` type

#### 3.1.4. `Datastore` Query configuration

The queries performed by the `Datastore` to fetch the data from backend can be configured using the `DatastoreDataProvider` builder API.

##### Query filters and sorts

The query filters and sorts can be configured in two ways:

1. At construction time, using the appropriate builder methods:

The `DatastoreDataProvider` builder API provide methods to:

- Add one or more `QueryFilter` to the query definition. These filters will always be included in the query execution.

- Add one or more `QuerySort` to the query definition. These sorts will always be included in the query execution.

- Set a default `QuerySort`, which will be used when no other sort is configured for the query.

    DataProvider<?, ?> dataProvider = DatastoreDataProvider.builder(datastore, TARGET, SUBJECT) (1)
        .withQueryFilter(NAME.isNotNull()) (2)
        .withQuerySort(NAME.asc()) (3)
        .withDefaultQuerySort(ID.desc()) (4)
        .build();

1 | Get a `DatastoreDataProvider` builder
2 | Add a query filter
3 | Add a query sort
4 | Set the default query sort

2. Dynamically, using a `QueryConfigurationProvider`:

One or more `QueryConfigurationProvider` references can be configured for the query using the `DatastoreDataProvider` builder API.

At each query execution, the `getQueryFilter()` and `getQuerySort()` methods of each available `QueryConfigurationProvider` will be invoked to obtain the filters and sorts to add to the query, if any.

    DataProvider<?, ?> dataProvider = DatastoreDataProvider.builder(datastore, TARGET, SUBJECT) (1)
        .withQueryConfigurationProvider(new QueryConfigurationProvider() { (2)

          @Override
          public QueryFilter getQueryFilter() { (3)
            return null;
          }

          @Override
          public QuerySort getQuerySort() { (4)
            return null;
          }

        }).build();

1 | Get a `DatastoreDataProvider` builder
2 | Add a `QueryConfigurationProvider`
3 | At each query execution, this method will be invoked to obtain the query filters, if any
4 | At each query execution, this method will be invoked to obtain the query sorts, if any

##### `QuerySortOrder` conversion

When the standard Vaadin Flow `com.vaadin.flow.data.provider.QuerySortOrder` type is used for the data provider query configuration, the `DatastoreDataProvider` can be configured to control how a `QuerySortOrder` declaration is converted into a `QuerySort` definition.

For this purpose, the `DatastoreDataProvider` builder API allows to configure a `QuerySortOrder` conversion function.

    DataProvider<?, ?> dataProvider = DatastoreDataProvider.builder(datastore, TARGET, SUBJECT) (1)
        .querySortOrderConverter(querySortOrder -> { (2)
          // QuerySortOrder to QuerySort conversion logic omitted
          return null;
        }).build();

1 | Get a `DatastoreDataProvider` builder
2 | Set the `QuerySortOrder` conversion function

##### Item identifier

By default, the item itself is used as item identifier to discern each item from another within the query results. The item identification relies on the standard Java `equals` and `hashCode` object methods.

When a `PropertyBox` type item is used, the default item identification strategy relies on the property set identifier properties values, if declared.

| See the Identifier properties documentation section for details.

If a custom item identifier should be used, an item identifier provider function can be configured using the `DatastoreDataProvider` builder API. This function must provide the item identifier for each item obtained form query execution.

Example using a PropertyBox type item

    DataProvider<?, ?> dataProvider = DatastoreDataProvider.builder(datastore, TARGET, SUBJECT)
        .itemIdentifierProvider(propertyBox -> propertyBox.getValue(ID)) (1)
        .build();

1 | Set an item identifier provider function which provides the `ID` property value as item identifier

Example using a bean item

    DataProvider<?, ?> dataProvider = DatastoreDataProvider.builder(datastore, TARGET, MyBean.class)
        .itemIdentifierProvider(bean -> bean.getId()) (1)
        .build();

1 | Set an item identifier provider function which provides the bean id value as item identifier using the `getId()` method

#### 3.1.5. Setup a `Datastore` data provider using builders

The Holon Platform Vaadin Flow module builder APIs provides covenient methods to setup a `Datastore` based data provider for UI components which support data binding.

Example for a single select, implemented using a Vaadin `ComboBox` component:

    SingleSelect<Long> select = Components.input.singleSelect(ID).dataSource(datastore, TARGET).build();

See Component builders and providers to learn about the available component builders.

### 3.2. Internationalization

The Holon Platform Vaadin Flow module provides a complete integration with the Holon Platform internationalization architecture, making UI components and messages localization simple and conistent with the full application stack.

Each localizable messages is represented by:

- A required message code, i.e. the `String` key to be used to obtain the message localization for a given `Locale`.

- An optional default message, to be used if a localized message is not available for a `Locale`.

- A set of optional localization arguments, which can be used to replace a specific placeholder with the actual values.

The localizable message attributes described above can be declared and represented using the Localizable interface, which provides convenient methods to create `Localizable` instances providing the message localization attributes.

The UI component builders which allow to setup localizable messages and texts, always support the `Localizable` API to provide the message localization attributes, providing also convenient methods to directly set the message localization attributes.

Example using a button component builder:

    Button button = Components.button().text("Not localizable").build(); (1)

    button = Components.button().text("Default message", "message.localization.code").build(); (2)

    button = Components.button().text("Default message", "message.localization.code", "arg1", "arg2").build(); (3)

    Localizable message = Localizable.of("Default message", "message.localization.code");
    button = Components.button().text(message).build(); (4)

1 | Set the button text using a not localizable message
2 | Set the button text using a localizable message, providing the default message and the localization code
3 | Set the button text using a localizable message, also providing two message localization arguments
4 | Set the button text using a `Localizable` reference

See Component builders and providers to learn about the available component builders.

#### 3.2.1. LocalizationContext and LocalizationProvider

The Holon Platform internationalization support relies on the LocalizationContext API, which acts as message resolver, localized data formatter and holder for the current user `Locale`.

In order for the UI components localization to work, one of the following conditions must be met:

- A `LocalizationContext` is available as context resource and a `Locale` is configured. See the Holon Platform Context architecture for information about the context resources management.

- Otherwise, a Vaadin Flow `I18NProvider` is available from the current Vaadin Service.

| See Vaadin session scope to learn about the context scope for resources bound to the current Vaadin application session.

The LocalizationProvider API is used by the UI components and builders to obtain the localization information and to localize the messages to display.

The `LocalizationProvider` API makes available a set of static methods to seamlessy integrate the messages localization in any part of the application, delegating the actual internationalization logic to the concrete localization provider, if available, which can be either a Holon Platform `LocalizationContext` or a Vaadin Flow `I18NProvider`.

The actual localization service to use is automatically detected with the following strategy:

- If a Vaadin Flow `I18NProvider` is available from current `VaadinService`, it is used for messages localization.

- Otherwise, a `LocalizationContext` is used if available as a context resource.

This way, the `LocalizationProvider` API `getLocalization` static methods can be used as follows:

    final Localizable message = Localizable.of("Default message", "message.localization.code");

    Optional<String> localized = LocalizationProvider.getLocalization(Locale.US, message); (1)
    String localizedOrDefault = LocalizationProvider.getLocalization(Locale.US, "Default message",
        "message.localization.code"); (2)

1 | Get the localization for the given `Localizable` message using the given `Locale`
2 | Get the localization for the given `message.localization.code` message code using the given `Locale` and the default `Default message` message if the localization is not available

If the `Locale` is not explicitly provided, the `LocalizationProvider` API `localize` static methods can be used and the current Locale is obtained with the following strategy:

- If a current `UI` is available and a `Locale` is configured for the `UI`, this one is used.

- If a `LocalizationContext` is available as a context resource and it is localized, the `LocalizationContext` current `Locale` is used.

- If a Vaadin Flow `I18NProvider` is available from current `VaadinService`, the first provided `Locale` is used if available.

    final Localizable message = Localizable.of("Default message", "message.localization.code");

    Optional<Locale> locale = LocalizationProvider.getCurrentLocale(); (1)

    Optional<String> localized = LocalizationProvider.localize(message); (2)
    String localizedOrDefault = LocalizationProvider.localize("Default message", "message.localization.code"); (3)

1 | Get the current `Locale`, if available
2 | Get the localization for the given `Localizable` message using the current `Locale`
3 | Get the localization for the given `message.localization.code` message code using the current `Locale`: the default `Default message` message is returned if the message localization or the current `Locale` is not available

#### 3.2.2. Use a LocalizationContext as I18NProvider

The Holon Platform `LocalizationContext` can be used as a standard Vaadin Flow `I18NProvider` through the LocalizationContextI18NProvider API.

| See the LocalizationContext documentation for information about the `LocalizationContext` configuration and use.

The `LocalizationContextI18NProvider` provides static methods to build a `I18NProvider` instance which uses a `LocalizationContext` as message localizations provider.

    LocalizationContext localizationContext = LocalizationContext.builder()
        .withMessageProvider(MessageProvider.fromProperties("messages").build()) (1)
        .withInitialLocale(Locale.US) (2)
        .build();

    I18NProvider i18nProvider = LocalizationContextI18NProvider.create(localizationContext); (3)

1 | Set the messages localization source
2 | Set the initial `Locale`
3 | Create a `I18NProvider` instance using the `LocalizationContext` as message localization provider

A `LocalizationContextI18NProvider` which uses the current `LocalizationContext` (if available as a context resource) can be obtained with the `create()` method:

    LocalizationContext localizationContext = LocalizationContext.builder()
        .withMessageProvider(MessageProvider.fromProperties("messages").build()).withInitialLocale(Locale.US)
        .build(); (1)

    VaadinSession.getCurrent().setAttribute(LocalizationContext.class, localizationContext); (2)

    I18NProvider i18nProvider = LocalizationContextI18NProvider.create(); (3)

1 | Create a `LocalizationContext`
2 | Put the `LocalizationContext` instance as a Vaadin Session attribute
3 | Create a `I18NProvider` instance which uses the current `LocalizationContext`

### 3.3. The `HasComponent` interface

Many of the additional UI components provided by the Holon Platform Vaadin Flow module extends the HasComponent interface to make available the actual Vaadin `com.vaadin.flow.component.Component` which can be used in the application UI.

The `getComponent()` method should be used to obtain the actual `Component`, for example to add it to a layout.

This because all the Holon UI components are represented using an interface, while the Vaadin `Component` object is a class. For this reason, the UI component interface cannot directly extend a class and the actual Vaadin `Component` is thus provided through the `getComponent()` method.

Example for an `Input` type component:

    Input<String> input = Input.string().build(); (1)

    VerticalLayout layout = new VerticalLayout();
    layout.add(input.getComponent()); (2)

1 | Create a String type `Input`
2 | Use the `getComponent()` method to add the actual input component to a layout

All the Holon UI components interfaces are located in the `com.holonplatform.vaadin.flow.components` package.

Furthermore, the `HasComponent` API provides methods to check if the actual component supports a set of features and to obtain the appropriate interface which allow to manage a specific feature.

Some of the component features which can be checked and accessed are:

- Enabled mode: using `hasEnabled()`.

- Size: using `hasSize()`.

- Style: using `hasStyle()`.

- Label: using `hasLabel()`.

    Input<String> input = Input.string().build(); (1)

    input.hasEnabled().ifPresent(e -> e.setEnabled(false)); (2)
    input.hasSize().ifPresent(s -> s.setSizeFull()); (3)
    input.hasStyle().ifPresent(s -> s.addClassName("my-style")); (4)
    input.hasLabel().ifPresent(l -> l.setLabel("My label")); (5)

1 | Create a String type `Input`
2 | Check if the component supports the enabled mode and if so set it to `false`
3 | Check if the component supports size and if so set it to full
4 | Check if the component supports style and if so add a CSS style class name
5 | Check if the component supports a label and if so set it to `My label`

### 3.4. The `ValueHolder` interface

The ValueHolder API is the abstract representation for components which handle a typed value, allowing to get and set the value according to the value type with which they are declared.

A set of convenience methods are provided to check if the value holder is empty (i.e. has no value) and to clear the value.

See View components and forms and Input components and forms to check two `ValueHolder` implementations.

    Input<String> input = Input.string().build(); (1)

    input.setValue("String value"); (2)
    String value = input.getValue(); (3)
    Optional<String> optionalValue = input.getValueIfPresent(); (4)

    boolean empty = input.isEmpty(); (5)
    input.clear(); (6)

1 | Create a `String` type `Input`, which extends `ValueHolder`
2 | Set the value
3 | Get the value
4 | Get the value, if present
5 | Check whether the input is empty
6 | Clear the value

Furthermore, the `ValueHolder` type components allow to listen to value changes, using a `ValueChangeListener`. The value change event provides both the changed and the previous value, and the information about the value change context, including whether the value change was originated by a user action or programmatically.

    Input<String> input = Input.string().build(); (1)

    input.addValueChangeListener(event -> { (2)
      String oldValue = event.getOldValue(); (3)
      String newValue = event.getValue(); (4)
      boolean byUser = event.isUserOriginated(); (5)
    });

1 | Create a `String` type `Input`, which extends `ValueHolder`
2 | Add a `ValueChangeListener`
3 | Get the previous value
4 | Get the changed value
5 | Get whether the value change was originated by a user action or programmatically

### 3.5. Component builders and providers

The Components API is the main entry point to build and configure the UI components.

It provides a complete set of methods to obtain fluent builders to create and configure both standard Vaadin Flow components and the additional UI components provided by the Holon Platform Vaadin Flow module.

The `Components` API structure:

Sub-interface | Provides
--- | ---
[NONE] | A set of configure(*) methods to setup existing standard component instances and a set of methods to obtain the fluent builders for base Vaadin components, such as `Button` and standard layout components. See Base components builders.
dialog | Message and question dialogs builders. See Dialogs.
view | Builders for view components and forms. See View components and forms.
input | Builders input components and forms. See Input components and forms.
listing | Builders for grid type components to list data. See List data in grids.

#### 3.5.1. Component builders structure

Each component builder API is composed by a set of specific builders, each related to a specific feature of the component. The feature builders are independent from the specific UI component to build, thus providing a common API which makes component configuration simple and intuitive.

For example, the HasTextConfigurator represents a builder part for UI components which supports a text, and it is included in any builder for UI components with text support.

Similarly, the the HasSizeConfigurator API is included in component builders which supports the component size configuration.

This ensures a consistent and common API to build and configure any UI component.

In the example below, the `HasTextConfigurator` and the `HasSizeConfigurator` are used in the same way to configure a label and a button component text and size:

    Div label = Components.label() (1)
        .text("Label text") (2)
        .width("200px") (3)
        .build();

    Button button = Components.button() (4)
        .text("Button text") (5)
        .width("200px") (6)
        .build();

1 | Get a label component builder
2 | Set the label text (using the `HasTextConfigurator` API)
3 | Set the label width (using the `HasSizeConfigurator` API)
4 | Get a button component builder
5 | Set the button text (using the `HasTextConfigurator` API)
6 | Set the button width (using the `HasSizeConfigurator` API)

#### 3.5.2. Base components builders

##### Button

The `Components.button()` method provides a standard Vaadin `Button` component builder, with localizable text support.

    Button button = Components.button() (1)
        .text("Button text") (2)
        .text("Default text", "message.code") (3)
        .description("The description") (4)
        .fullWidth() (5)
        .styleName("my-style") (6)
        .withThemeVariants(ButtonVariant.LUMO_PRIMARY) (7)
        .icon(VaadinIcon.CHECK) (8)
        .disableOnClick() (9)
        .onClick(event -> { (10)
          // do something
        }).build();

    button = Components.button("Button text", e -> {
      /* do something */ }); (11)

1 | Get the `Button` builder
2 | Set the button text
3 | Set the button localizable text, providing a default text and a message localization code
4 | Set the button description
5 | Set the button width to 100%
6 | Add a CSS style class name
7 | Add a theme variant
8 | Set the button icon
9 | Automatically disables button when clicked
10 | Add a click event listener
11 | Shorter to directly create a `Button` providing the text and the click handler

The `Components.nativeButton()` builder can be used to build a `NativeButton` component.

##### Label

A label component can be used to display a text, which can be localizable, and can be implemented using a set of tags. The default tag used by the `Components.label()` method is `DIV`.

| See Internationalization for information about the UI components text localization.

    Div label = Components.label() (1)
        .text("Label text") (2)
        .text("Default text", "message.code") (3)
        .description("The description") (4)
        .fullWidth() (5)
        .styleName("my-style") (6)
        .build();

1 | Get a label builder using a `Div` component
2 | Set the label text
3 | Set the label localizable text, providing a default text and a message localization code
4 | Set the label description
5 | Set the label width to 100%
6 | Add a CSS style class name

Other builders are available for the tags: `P`, `SPAN`, `H1`, `H2`, `H3`, `H4`, `H5`, `H6`.

    Paragraph p = Components.paragraph().text("text").build(); (1)
    Span span = Components.span().text("text").build(); (2)
    H1 h1 = Components.h1().text("text").build(); (3)
    H2 h2 = Components.h2().text("text").build(); (4)
    H3 h3 = Components.h3().text("text").build(); (5)
    H4 h4 = Components.h4().text("text").build(); (6)
    H5 h5 = Components.h5().text("text").build(); (7)
    H6 h6 = Components.h6().text("text").build(); (8)

1 | Get a label builder using a `Paragraph` component
2 | Get a label builder using a `Span` component
3 | Get a label builder using a `H1` component
4 | Get a label builder using a `H2` component
5 | Get a label builder using a `H3` component
6 | Get a label builder using a `H4` component
7 | Get a label builder using a `H5` component
8 | Get a label builder using a `H6` component

##### Layouts

The Vaadin Flow base layouts can be created and configured using the following builders:

- *Vertical layout: * `Components.vl()`.

- *Horizontal layout: * `Components.hl()`.

- *Form layout: * `Components.formLayout()`.

    VerticalLayout verticalLayout = Components.vl() (1)
        .spacing() (2)
        .margin() (3)
        .alignItems(Alignment.CENTER) (4)
        .justifyContentMode(JustifyContentMode.END) (5)
        .fullSize() (6)
        .styleName("my-style") (7)
        .add(Components.button().text("Button text").build()) (8)
        .add(Components.label().text("Label1").build(), Components.label().text("Label2").build()) (9)
        .addAndAlign(myComponent1, Alignment.START) (10)
        .build();

    HorizontalLayout horizontalLayout = Components.hl() (11)
        .add(myComponent1) (12)
        .add(myComponent2) (13)
        .flexGrow(1, myComponent1) (14)
        .build();

    FormLayout formLayout = Components.formLayout() (15)
        .add(myComponent1) (16)
        .withFormItem(myComponent1, "Label 1") (17)
        .responsiveSteps(new ResponsiveStep("100px", 2)) (18)
        .build();

1 | Get a `VerticalLayout` builder
2 | Enable spacing
3 | Enable margins
4 | Set the default component alignment
5 | Set the justify content mode
6 | Set width and height to 100%
7 | Add a CSS style class name
8 | Add a Button component
9 | Add two label components
10 | Add a component and set its alignment
11 | Get a `HorizontalLayout` builder
12 | Add a component
13 | Add another component
14 | Set the flex grow ratio for the first component
15 | Get a `FormLayout` builder
16 | Add a component
17 | Add a FormItem slot with a component and its label
18 | Set the responsive steps

##### Context menu

The `Components.contextMenu()` method can be used to configure a `ContextMenu` and bind it to a component.

    Components.contextMenu() (1)
        .withItem("Item 1").onClick(e -> {
          // do something
        }).add() (2)
        .withItem("Item 2", "message.code").disabled().add() (3)
        .withItem(itemComponent).add() (4)
        .withOpenedChangeListener(e -> { (5)
          e.isOpened();
        }).build(myComponent); (6)

1 | Get a `ContextMenu` builder
2 | Add a menu item with a text and a click handler
3 | Add disabled a menu item with a localizable text
4 | Add a menu item using a component
5 | Add a menu open change listener
6 | Build the `ContextMenu` and bind it to the `myComponent` component

#### 3.5.3. Base components configurators

Besides the builders, the `Components` API provides a set of configurator methods, which can be used to configure existing UI components. The available configurators acts on some base UI components: label, Button and layouts.

    Button btn = new Button();

    Components.configure(btn).text("Default text", "message.code"); (1)

    VerticalLayout vl = new VerticalLayout();

    Components.configure(vl).withoutSpacing().add(myComponent); (2)

1 | Configure the `Button`, setting a localizable text
2 | Configure the `VerticalLayout`, disabling spacing and adding a component

### 3.6. Dialogs

The `Components.dialog` sub-interface provides a set of method to build and configure a Vaadin Flow `Dialog`. Three types of dialogs are available, as described below.

#### 3.6.1. Message Dialog

A message dialog is a `Dialog` which can be used to display a simple message to the user.

    Dialog dialog = Components.dialog.message().text("Message").build(); (1)

    Components.dialog.message().text("Default text", "message.code").open(); (2)

    Components.dialog.showMessage("Default text", "message.code"); (3)

1 | Build a message `Dialog` with given message text
2 | Build a message `Dialog` with given localizable message text and open it
3 | Shorter to build and show a message `Dialog` with a localizable message text

#### 3.6.2. Confirm Dialog

A confirm dialog is a `Dialog` which can be used to display a simple message to the user and provides a `OK` button at the bottom right position.

The `OK` button can be configured using the dialog builder.

    Components.dialog.confirm() (1)
        .text("Default text", "message.code") (2)
        .okButtonConfigurator(button -> { (3)
          button.text("My text").icon(VaadinIcon.CHECK);
        }).open(); (4)

    Components.dialog.showConfirm("Default text", "message.code"); (5)

1 | Get a confirm `Dialog` builder
2 | Set the localizable dialog message
3 | Configure the confirm dialog OK button
4 | Build and open the dialog
5 | Shorter to build and show a confirm `Dialog` with a localizable message text

#### 3.6.3. Question Dialog

A question dialog is a `Dialog` which can be used to ask a question to the user and handle the user answer. A `QuestionDialogCallback` function must be provided to handle the user answer.

Two buttons are displayed at the bottom right position, which by default represents the `yes` or `no` answers. The buttons can be configured using the dialog builder.

    Components.dialog.question(confirm -> { (1)
      // handle user response (true/false)
    }).text("Default text", "message.code") (2)
        .confirmButtonConfigurator(button -> { (3)
          // confirm button configuration
        }).denialButtonConfigurator(button -> { (4)
          // deny button configuration
        }).open(); (5)

    Components.dialog.showQuestion(confirm -> {
      /* handle user response */ }, "Default text", "message.code"); (6)

1 | Get a question `Dialog` builder, providing the user answer callback
2 | Set the localizable dialog message
3 | Configure the confirm dialog button
4 | Configure the deny dialog button
5 | Build and open the dialog
6 | Shorter to build and show a question `Dialog` with a localizable message text

#### 3.6.4. Dialog configuration options

All the dialog builders provides a set of common `Dialog` configuration options, including:

- Dialog size configuration

- Dialog style configuration

- Dialog closing mode configuration and open change listener

    Components.dialog.message().text("Default text", "message.code") //
        .width("200px") (1)
        .height("200px") (2)
        .styleName("my-style") (3)
        .closeOnEsc(false) (4)
        .closeOnOutsideClick(true) (5)
        .withOpenedChangeListener(event -> { (6)
          // open changed
        }).build();

1 | Set the dialog width
2 | Set the dialog height
3 | Add a CSS style class name
4 | Disable closing when `ESC` pressed
5 | Enable closing when user clicks outside the dialog
6 | Add a open change listener

#### 3.6.5. Adding components to the Dialog

The dialog builders allow to add custom components to the `Dialog` content. The components can be added in two positions:

- In the main dialog content: will be placed after the dialog message label, if any.

- In the dialog bottom toolbar: will be placed before the standard dialog buttons, if any.

    Components.dialog.message().text("Default text", "message.code") //
        .withComponent(Components.label().text("My label").build()) (1)
        .withToolbarComponent(Components.button().text("My button").build()) (2)
        .open();

1 | Add a label component in the dialog content area
2 | Add a button component in the dialog toolbar

### 3.7. List data in grids

The ItemListing API represents a UI component which can be used to display data in a tabular way.

Extends `HasComponent` (see The `HasComponent` interface) and it is actually implemented using a Vaadin Flow `Grid` component.

A `ItemListing` is designed to display a set of data items of a specific type, each one rendered as a list row. An item is a collection of values, and each value is bound to a property definition of a specific type.

Each `ItemListing` column is bound to an item property by default, even if virtual or calculated columns can be added to the listing.

Two `ItemListing` implementations are available:

- `PropertyListing`: to use the Holon Platform property model to represent the item properties and the `PropertyBox` type as item representation. See PropertyListing.

- `BeanListing`: to use a Java Bean class as item type and the bean property names as item properties. See BeanListing.

Each item listing implementation provides one or more suitable `builder` methods to obtain the fluent builder to use to create and configure an item listing instance.

The same builders are also available from the `Components` API, through the `Components.listing` sub interface. See Component builders and providers.

#### 3.7.1. PropertyListing

The PropertyListing API is the default `ItemListing` implementation which uses the Holon Platform Property model to represent and manage the data items.

- A property set must be provided at `PropertyListing` costruction time. It represents the available item properties, each one bound by default to a listing column.

- The `PropertyBox` type is used to represent an item instance, using the listing property set. So each listing row is bound to a `PropertyBox` instance, which collects the property values to be displayed for each listing column.

For example, given the following property model definition:

    static final NumericProperty<Long> ID = NumericProperty.longType("id");
    static final StringProperty NAME = StringProperty.create("name");
    static final PropertySet<?> SUBJECT = PropertySet.of(ID, NAME);

A `PropertyListing` can be created in the following way:

    PropertyListing listing = PropertyListing.builder(SUBJECT).build(); (1)

    listing = Components.listing.properties(ID, NAME).build(); (2)

    new VerticalLayout().add(listing.getComponent()); (3)

1 | Build a `PropertyListing` using the `SUBJECT` property set. The listing will provide two columns, one bound to the `ID` item property and the other bound to the `NAME` item property
2 | Build a `PropertyListing` using the `Components` API, directly providing the `ID` and `NAME` properties as listing property set
3 | Just like any `HasComponent` component type, the `getComponent()` method should be used to obtain the actual listing Component

#### 3.7.2. BeanListing

The BeanListing API is the default `ItemListing` implementation to use a Java Bean class as item type.

- A bean class must be provided at `BeanListing` costruction time. The bean class property names will be used as listing property set and so rendered as listing columns. For this reason the item listing property definition type is a `String`.

- Each listing row is bound to a bean class instance, and the bean class getters will be used to obtain the property value to be rendered for each listing column.

For example, given the following bean class definition:

    class MyBean {

      private Long id;
      private String name;

      public MyBean() {
        super();
      }

      public MyBean(Long id, String name) {
        super();
        this.id = id;
        this.name = name;
      }

      public Long getId() {
        return id;
      }

      public void setId(Long id) {
        this.id = id;
      }

      public String getName() {
        return name;
      }

      public void setName(String name) {
        this.name = name;
      }

    }

A `BeanListing` can be created in the following way:

    BeanListing<MyBean> listing = BeanListing.builder(MyBean.class).build(); (1)

    listing = Components.listing.items(MyBean.class).build(); (2)

    new VerticalLayout().add(listing.getComponent()); (3)

1 | Build a `BeanListing` using the `MyBean` class. The listing will provide two columns, one bound to the `id` bean property name and the other bound to the `name` bean property name
2 | Build a `BeanListing` using the `Components` API
3 | Just like any `HasComponent` component type, the `getComponent()` method should be used to obtain the actual listing Component

#### 3.7.3. Item listing data source

To obtain the item set to display, an item listing needs a data source to be configured. This can be achieved either using the `items(…​)` or the `datasource(…​)` builder methods, to provide a static set of items or a backend data connection respectively.

1. Using a static set of items:

The item listing item set can be provided at listing costruction time, using the `items(…​)` or `addItem(…​)` builder methods. The provided item instances must be of the same type of the listing item type.

The provided item will be displayed in the same order they are provided at construction time.

Example using a `PropertyListing`:

    PropertyListing listing = PropertyListing.builder(SUBJECT) (1)
        .items(PropertyBox.builder(SUBJECT).set(ID, 1L).set(NAME, "One").build()).build();

    listing = PropertyListing.builder(SUBJECT) (2)
        .addItem(PropertyBox.builder(SUBJECT).set(ID, 1L).set(NAME, "One").build())
        .addItem(PropertyBox.builder(SUBJECT).set(ID, 2L).set(NAME, "Two").build()).build();

1 | Set the listing items
2 | Set the listing items using `addItem(…​)`

Example using a `BeanListing`:

    BeanListing<MyBean> listing = BeanListing.builder(MyBean.class) (1)
        .items(new MyBean(1L, "One"), new MyBean(2L, "Two")).build();

    listing = BeanListing.builder(MyBean.class) (2)
        .addItem(new MyBean(1L, "One")) //
        .addItem(new MyBean(2L, "Two")).build();

1 | Set the listing items
2 | Set the listing items using `addItem(…​)`

2. Using a `DataProvider`:

A Vaadin `com.vaadin.flow.data.provider.DataProvider` can be used as items data source. This allows to provide a dynamic set of items, for example using a backend service.

The `DataProvider` data type must be consistent with the listing item type.

Example using a `PropertyListing`:

    DataProvider<PropertyBox, ?> dataProvider = getPropertyBoxDataProvider(); (1)

    PropertyListing listing = PropertyListing.builder(SUBJECT).dataSource(dataProvider) (2)
        .build();

1 | Obtain a `DataProvider` using the `PropertyBox` data type
2 | Set the data provider as listing data source

Example using a `BeanListing`:

    DataProvider<MyBean, ?> dataProvider = getBeanDataProvider(); (1)

    BeanListing<MyBean> listing = BeanListing.builder(MyBean.class).dataSource(dataProvider) (2)
        .build();

1 | Obtain a `DataProvider` using the `MyBean` data type
2 | Set the data provider as listing data source

When a `DataProvider` is used as data source, the `refresh()` and `refreshItem(T item)` can be used to refresh the listing item set:

- The `refresh` method can be used to refresh the whole item set. In most cases, the data provider configured as data source will execute again a query to obtain the data from the backend.

- The `refreshItem` method can be used to refresh a single item, providing an updated instance to be included in the listing item set, replacing the previous one.

    PropertyListing listing = PropertyListing.builder(SUBJECT).dataSource(getDataProvider()).build(); (1)

    listing.refresh(); (2)
    listing.refreshItem(itemToRefresh); (3)

1 | Create a listing and use a data provider as data source
2 | Refresh all the listing items
3 | Refresh a specific item

#### 3.7.4. Using a `Datastore` as item listing data source

The Holon Platform Datastore API can be used to implement a listing data source, and maybe it is the most straight and easy way to connect a property model based listing to a backend data source.

This first way to use a `Datastore` as listing data source is to use the `DataProvider` adapter, available through the DatastoreDataProvider API.

See the Datastore API integration section to learn how to create and configure a `Datastore` based `DataProvider`.

When a `Datastore` is used, a `DataTarget` definition is required to declare the data model entity to use as items data source (for example a RDBMS table name, or a collection name in a document based database).

Supposing to use the following `DataTarget` definition:

    static final DataTarget<?> TARGET = DataTarget.named("subjects");

A `PropertyListing` data source can be declared as follows:

    Datastore datastore = getDatastore();

    PropertyListing listing = PropertyListing.builder(SUBJECT) (1)
        .dataSource(DatastoreDataProvider.create(datastore, TARGET, SUBJECT)) (2)
        .build();

1 | Create a `PropertyListing` using the `SUBJECT` property set
2 | Use the `DatastoreDataProvider` API to create a data provider which uses the provided `Datastore` and `DataTarget` to perform backend data queries

But the most straight and easy way to use a `Datastore` as listing data source is to rely on the listing builder methods available for this purpose. Furthermore, the builder methods allow to avoid to specify the query projection property set again, using the listing property set by default.

    Datastore datastore = getDatastore();

    PropertyListing listing = PropertyListing.builder(SUBJECT) (1)
        .dataSource(datastore, TARGET) (2)
        .build();

1 | Create a `PropertyListing` using the `SUBJECT` property set
2 | Directly use the `dataSource` builder method to create a data provider which uses the provided `Datastore` and `DataTarget` to perform backend data queries. In this case, there is no need to specify the `SUBJECT` property set, since the listing property set is used as query projection

The `dataSource` builder method turns the root listing builder in a Datastore-aware builder, making available a set of additional methods which can be used to configure the `Datastore` based data provider, for example to add query filters and sorts. The `Datastore` based data provider configuration methods corresponds to the ones provided by the `DatastoreDataProvider` API. See `Datastore` Query configuration for details.

    PropertyListing listing = PropertyListing.builder(SUBJECT) //
        .dataSource(getDatastore(), TARGET) (1)
        .withQueryFilter(NAME.isNotNull()) (2)
        .withQuerySort(ID.asc()) (3)
        .build();

1 | Set the listing data source using a `Datastore` and providing the data target to use
2 | Configure the `Datastore` data provider adding a query filter
3 | Configure the `Datastore` data provider adding a query sort

#### 3.7.5. Item listing frozen data source modality

The item listing data source can be set in a frozen state using the item listing API:

- When the item listing is in frozen state, it never shows any item and no fetch is performed from the data provider.

- When the item listing `refresh()` method is invoked, the frozen state is automatically disabled, allowing the listing to fetch and display the items.

The frozen state can be useful when you don’t want to fetch the items just after the listing is displayed in UI, maybe because it involves an onerous backend query. The backend query is only performed when the `refresh()` method is called, typically by a user explicit action.

The item listing frozen state can be configured either from the buider API or from the `ItemListing` API:

    PropertyListing listing = PropertyListing.builder(SUBJECT) //
        .frozen(true) (1)
        .build();

    listing.setFrozen(true); (2)

    boolean frozen = listing.isFrozen(); (3)

    listing.refresh(); (4)

1 | Use the builder API to set the listing in frozen state
2 | Use the listing API to set the listing in frozen state
3 | Check whether the listing is in frozen state
4 | Calling `refresh()` will disable the frozen state, allowing the listing to fetch and display the items

#### 3.7.6. Item listing data source additional items

The `ItemListing` API supports additional data source items. Additional items can be added using the `ItemListing` API and they will appear as conventional listing items, even they are not part of the items returned by the concrete data source.

Additional items can be used, for example, to allow the user to add an item to the listing, edit its data and then saving the item in the concrete datastore. At this point, the additional item can be removed, since the saved item will now be returned by the data source query.

The `ItemListing` API provides method to manage additional items: add an additional item, remove an additional item, remove all additional items and obtain the current additional items.

    PropertyListing listing = PropertyListing.builder(SUBJECT).build();

    listing.addAdditionalItem(myItem); (1)

    List<PropertyBox> additionalItems = listing.getAdditionalItems(); (2)

    listing.removeAdditionalItem(myItem); (3)

    listing.removeAdditionalItems(); (4)

1 | Add an additional item
2 | Get the current additional items
3 | Remove the additional item
4 | Remove all the additional items

#### 3.7.7. Item listing configuration

The item listing builders provides a set of methods to configure the item listing component, most of them coming from the Vaadin `Grid` component configuration options.

This includes for example setting the page size, setting whether the listing column are resizable and can be reordered, setting the frozen columns and so on.

    PropertyListing listing = PropertyListing.builder(SUBJECT) //
        .pageSize(50) (1)
        .columnReorderingAllowed(true) (2)
        .resizable(true) (3)
        .frozenColumns(1) (4)
        .heightByRows(true) (5)
        .verticalScrollingEnabled(true) (6)
        .multiSort(true) (7)
        .build();

1 | Sets the page size (the number of items fetched at a time from the data source)
2 | Set whether the columns can by reordered by the user
3 | Set whether the columns can by resized by the user
4 | Set the number of frozen columns, i.e. the fixed columns, not involved in horizontal scrolling
5 | Set whether the listing’s height is defined by the number of its rows
6 | Set whether the vertical scrolling is enabled
7 | Set whether multiple column sorting is enabled on the client-side

#### 3.7.8. Listen to listing row clicks

One ore more item click listener can be added to the listing to handle user clicks on the listing rows. The click event provides the clicked item instance and a reference to the listing on which the click occurred.

Furthermore, a set of additional click information are provided, such as the click count, the modifier keys, the screen coordinates and so on.

    PropertyListing listing = PropertyListing.builder(SUBJECT) //
        .withItemClickListener(event -> { (1)
          PropertyBox clickedItem = event.getItem(); (2)
          PropertyListing source = event.getSource(); (3)
          event.getClickCount(); (4)
          event.getButton(); (5)
          event.isCtrlKey(); (6)
          /* other getters omitted */
        }).build();

1 | Add an item click listener
2 | Get the item instance on which the click occurred
3 | Get the item listing reference
4 | Get the consecutive clicks count
5 | Get the mouse button, if available
6 | Check whether the CTRL key was down when the click occurred

#### 3.7.9. Configure the item listing columns

The item listing columns are auto-generated by default using the provided listing property set.

- `PropertyListing`: each property declared in the property set will be rendered as a column. You can refer to a column using the corresponding property definition.

- `BeanListing`: each available bean property will be rendered as a column. You can refer to a column using the corresponding bean property name.

##### Change the column order and visibility

A set of builder methods are available to change the listing column display order. The builder methods allow to:

- Explicitly provide the column to show and their order.

- Declare the column position relative to another column (before or after)

- Display a column as first or last in the columns set

- Set a column as hidden

    PropertyListing listing = PropertyListing.builder(SUBJECT) //
        .visibleColumns(NAME, ID) (1)
        .displayAsFirst(NAME) (2)
        .displayAsLast(ID) (3)
        .displayBefore(NAME, ID) (4)
        .displayAfter(ID, NAME) (5)
        .hidden(ID) (6)
        .build();

    BeanListing<MyBean> listing2 = BeanListing.builder(MyBean.class) (7)
        .visibleColumns("name", "id").displayAsFirst("name").hidden("id").build();

1 | Declare the visibile columns and the display order
2 | Set the `NAME` column to be displayed as first
3 | Set the `ID` column to be displayed as last
4 | Set the `NAME` column to be displayed before the `ID` column
5 | Set the `ID` column to be displayed after the `NAME` column
6 | Set the `ID` column as hidden
7 | Example using a `BeanListing`

##### Column configuration

The item listing builder provides a set of methods to configure a listing column, including:

- Se the column header, with localizable messages support. See Internationalization.

- Se the column footer, with localizable messages support. See Internationalization.

- Set the column width and alignment

- Set whether the column is resizable by the user

- Set whether the column is sortable and optionally provide the sort logic

- Set the column value provider and renderer

- Set whether the column is frozen, i.e. fixed and not involved in horizontal scrolling

    PropertyListing listing = PropertyListing.builder(SUBJECT) //
        .header(NAME, "The name") (1)
        .header(NAME, "The name", "name.message.code") (2)
        .headerComponent(NAME, new Button("name")) (3)
        .width(NAME, "100px") (4)
        .flexGrow(NAME, 1) (5)
        .alignment(NAME, ColumnAlignment.CENTER) (6)
        .footer(NAME, "Footer text") (7)
        .resizable(NAME, true) (8)
        .sortable(NAME, true) (9)
        .sortUsing(NAME, ID) (10)
        .sortProvider(NAME, direction ->
        /* sort logic omitted */
        null) (11)
        .valueProvider(NAME, item -> item.getValue(NAME)) (12)
        .renderer(NAME, new TextRenderer<>()) (13)
        .frozen(NAME, true) (14)
        .build();

1 | Set the `NAME` column header
2 | Set the `NAME` column header using a localizable message
3 | Set the `NAME` column header using a `Component`
4 | Set the `NAME` column width
5 | Set the `NAME` column flex grow ratio
6 | Set the `NAME` column alignment
7 | Set the `NAME` column footer
8 | Set whether the `NAME` column is resizable
9 | Set whether the `NAME` column is sortable
10 | Set that the `ID` property must be used to sort the `NAME` column
11 | Set the `NAME` column sort logic
12 | Set the `NAME` column value provider
13 | Set the `NAME` column renderer
14 | Set the `NAME` column as frozen

##### Adding columns

New virtual columns can be added to an item listing, i.e. columns which are not directly bound to an item property.

A virtual column can be used for example to display a calculated result, using the item instance property values, or to display a UI component.

1. Add a virtual column:

A new column can be added to the listing using the `withColumn` builder method and providing a function to obtain the column value, given the current row item instance (a `PropertyBox` for a `PropertyListing` and a bean class instance for a `BeanListing`.

The added column can be configured, with the same configuration options described in the section above. Then, the column is added to the listing using the `add()` method.

Example using a `PropertyListing`:

    PropertyListing listing = PropertyListing.builder(SUBJECT) //
        .withColumn(item -> "Virtual: " + item.getValue(ID)) (1)
        .header("Virtual") (2)
        .displayBefore(NAME) (3)
        .add() (4)
        .build();

1 | Add a new virtual column, which uses the row item to provide its value
2 | Configure the added column setting the header text
3 | Set to display the added column before the `NAME` column
4 | Add the column to the listing

Example using a `BeanListing`:

    BeanListing<MyBean> listing2 = BeanListing.builder(MyBean.class) //
        .withColumn(item -> "Virtual: " + item.getId()) (1)
        .header("Virtual") (2)
        .displayAsFirst() (3)
        .add() (4)
        .build();

1 | Add a new virtual column, which uses the row item to provide its value
2 | Configure the added column setting the header text
3 | Set to display the added column as first
4 | Add the column to the listing

2. Add a `Component` type column:

A convenience `withComponentColumn` method is available to add a Vaadin `Component` type column, automatically configuring a suitable Component renderer for the column itself.

Just like a virtual column, the column can be configured and then the `add()` method should be used to add it to the listing.

    PropertyListing listing = PropertyListing.builder(SUBJECT) //
        .withComponentColumn(item -> new Button(item.getValue(NAME))) (1)
        .header("Component") (2)
        .sortUsing(NAME) (3)
        .add() (4)
        .build();

1 | Add a new `Component` type column, which provides a `Button` and uses the row item to set the button text
2 | Configure the added column setting the header text
3 | Set that the `NAME` property has to be used to sort the added column
4 | Add the column to the listing

#### 3.7.10. Default column value rendering strategy

If an explicit column renderer is not configured for a column, the default column value rendering strategy uses the Holon Platform StringValuePresenter API to render a column value.

This ensures a consistent behaviour across the application on how the values are displayed and the current `LocalizationContext` is used, if available, to apply the proper internationalization conventions to format, for example, a numeric value.

See the StringValuePresenter API documentation for details.

Furthermore, for a `PropertyListing` implementation, the PropertyValuePresenter architecture is used to render the column value, allowing to extend and tune the presentation strategy at higher level, ensuring consistency across the application UI and backend.

See the Property value presentation documentation for details.

For example, suppose we want to add a `#` prefix to each value of the `ID` property. We can declare a `PropertyValuePresenter` and bind it to the `ID` property in the property presenters registry:

    PropertyValuePresenterRegistry.getDefault() (1)
        .forProperty(ID, (property, value) -> "#" + value); (2)

1 | Get the default `PropertyValuePresenterRegistry`
2 | Register a `PropertyValuePresenter`, bound to the `ID` property, which adds a `#` prefix to the property value

From now on, any `PropertyListing` instance will use the new presenter to render the `ID` property column value.

    PropertyListing listing = PropertyListing.builder(SUBJECT).build(); (1)

    String value = ID.present(1L); (2)

1 | The `PropertyListing` instance will use the new presenter to render the `ID` property column value (so the `ID` column cells will show `#1`, `#2` and so on)
2 | Any other property presentation service will use the new presenter for the `ID` property value. In this example, the `ID` property is directly used to present the `1` value (declared as a Long) and the result will be the String `#1`.

#### 3.7.11. Render columns using Components

The `PropertyListing` builder makes available helper methods to render a column using a `Component`, providing the function to use to obtain the `Component` instance for each cell, given the current row `PropertyBox` item.

    PropertyListing listing = PropertyListing.builder(SUBJECT) //
        .componentRenderer(NAME, item -> { (1)
          return new Button(item.getValue(NAME));
        }).build();

1 | Render the column identified by the `NAME` property as a `Component`. In this example, a `Button` is returned, with button text setted as the current item `NAME` property value

#### 3.7.12. Render columns using a `ViewComponent`

A `PropertyListing` column can be rendered using a `ViewComponent`, leveraging the `ViewComponent` rendering architecture and thus providing a consistent data rendering strategy across all the application UI components.

See View components and forms for information about `ViewComponent` purpose and configuration.

    PropertyListing listing = PropertyListing.builder(SUBJECT) //
        .renderAsViewComponent(NAME) (1)
        .build();

1 | The column identified by the `NAME` property will be rendered using a `ViewComponent`

#### 3.7.13. Add a context menu

The item listing supports a context menu, which can be added to the listing and will open by default when a right click or a long tap is performed by the user on a listing row.

The item listing context menu builder provides a set of methods to:

- Add context menu item using a text, with message localization support.

- Add context menu item using a Component.

- Set the menu item click handler, providing an event form which to obtain the listing item instance of the row on which to context menu was opened and a reference to the item listing itself.

- Configure the context menu items.

    PropertyListing listing = PropertyListing.builder(SUBJECT) //
        .contextMenu() (1)
        .withItem("Context menu item 1") (2)
        .withClickListener(e -> { (3)
          PropertyBox rowItem = e.getItem(); (4)
          e.getItemListing(); (5)
          Notification.show("Context menu item clicked on row id " + rowItem.getValue(ID));
        }).add() (6)
        .withItem("Context menu item 2", "item.message.code", e -> {
          /* do something */}) (7)
        .withItem(new Button("Context menu item 3"), e -> {
          /* do something */}) (8)
        .add() (9)
        .build();

1 | Create a context menu for the listing: a context menu builder is returned to configure the menu items
2 | Add a menu item with given text
3 | Configure the menu item adding the click handler
4 | The click event provides the listing item instance of the row on which to context menu was opened
5 | The parent item listing can be obtained from the click event
6 | Add the context menu item to the context menu
7 | Add another context menu item, directly providing a localizable text and the item click handler
8 | Add a `Component` type context menu item, directly providing a `Button` and the item click handler
9 | Add the configured context menu to the item listing

#### 3.7.14. Manage row details components

The item listing supports row details components, which can be opened and closed under each listing row.

To enable the item row details, a function which provides the details content for each row has to be provided. For each row, the listing row item instance is provided as function argument.

The item details contents can be rendered in two ways:

- As a text: using the `itemDetailsText` builder method.

- As a `Component`: using the `itemDetailsComponent` builder method.

    PropertyListing listing = PropertyListing.builder(SUBJECT) //
        .itemDetailsText(item -> "Detail of: " + item.getValue(ID)) (1)
        .itemDetailsComponent(item -> new Button(item.getValue(NAME))) (2)
        .build();

1 | Set the item details renderer using text
2 | Set the item details renderer using a `Component`

By default, the item details are shown/hidden for each listing row when the user clicks on a row. This behaviour can be disabled using the `itemDetailsVisibleOnClick` builder method.

In this case, the item details content should be opened or closed programmatically. For this purpose, the `setItemDetailsVisible` method of the item listing API can be use to show or hide the item details for a specific item.

    PropertyListing listing = PropertyListing.builder(SUBJECT) //
        .itemDetailsText(item -> "Detail of: " + item.getValue(ID)) (1)
        .itemDetailsVisibleOnClick(false) (2)
        .withItemClickListener(e -> { (3)
          e.getSource().setItemDetailsVisible(e.getItem(), true);
        }).build();

1 | Set the item details renderer using text
2 | Disable the item details display at user click
3 | Add an item click listener to handle the item details display, using the `setItemDetailsVisible` method

#### 3.7.15. Header and footer configuration

The item listing header and footer sections can be completely customized, setting the cells contents and joining two or more cells together.

The header and footer sections handlers can be obtainer either using:

- The builder API, using the `header` and `footer` methods.

- The item listing API, using the `getHeader()` and `getFooter()` methods.

    PropertyListing listing = PropertyListing.builder(SUBJECT) //
        .header(header -> { (1)
          header.prependRow().join(ID, NAME).setText("A text");
        }).footer(footer -> { (2)
          footer.appendRow().getCell(ID).ifPresent(cell -> cell.setText("ID footer"));
        }).build();

    listing.getHeader().ifPresent(header -> { (3)
      /* customize header */
    });
    listing.getFooter().ifPresent(footer -> { (4)
      /* customize footer */
    });

1 | Use the builder to customize the header section
2 | Use the builder to customize the footer section
3 | Get the header section
4 | Get the footer section

#### 3.7.16. Handling row selection

The item listing supports both single and multiple row selection modes. When the listing is in multiple selection mode, a checkbox is shown before each listing row to allow user selection. Additionaly, a select all checkbox is available in the listing header first cell.

The item listing selection mode can be enabled either using:

- The builder API, using the `selectionMode` method (`NONE`, `SINGLE` or `MULTI`). The `singleSelect()` and `multiSelect()` convenience methods are provided as shorters for the single and multiple selection mode.

- The item listing API, using the `setSelectionMode` method (`NONE`, `SINGLE` or `MULTI`).

A `SelectionListener` can be added to the item listing in order to listen to item selection events and obtain the currently selected items.

Furthermore, the item listing API provides a set of methods to select or deselect one or more items programmatically.

    PropertyListing listing = PropertyListing.builder(SUBJECT) //
        .selectionMode(SelectionMode.SINGLE) (1)
        .singleSelect() (2)
        .multiSelect() (3)
        .withSelectionListener(event -> { (4)
          Set<PropertyBox> items = event.getAllSelectedItems(); (5)
          Optional<PropertyBox> item = event.getFirstSelectedItem(); (6)
        }).build();

    listing.setSelectionMode(SelectionMode.MULTI); (7)
    listing.addSelectionListener(event -> { (8)
    });

    listing.select(myItem); (9)
    listing.deselect(myItem); (10)
    listing.deselectAll(); (11)

1 | Set the listing selection mode
2 | Set the listing selection mode as single
3 | Set the listing selection mode as multiple
4 | Add a selection listener
5 | Get the selected items, if any
6 | Get the first selected item, if any
7 | Use the listing API to change the selection mode
8 | Add a selection listener
9 | Programmatically select an item
10 | Programmatically deselect an item
11 | Deselect all items

#### 3.7.17. Editing the listing items

The item listing supports an edit mode, which can be enabled using the `editable()` builder method.

When a listing is editable, a row can be setted in edit mode using the `editItem(T item)` method of the item listing API. When `editItem` is called, each cell content is replaced by an input component to allow to change the item property value which corresponds to each column.

The updated row item values can be saved using the `saveEditingItem()` method of the item listing API, or discarded using the `cancelEditing()` method. Then the row editor is closed, restoring the default cell contents.

A set of listeners can be added to the listing to control the editing process:

- `EditorSaveListener`: for editor save events, which corresponds to the `saveEditingItem()` method call. Can be used for example to update the data in the backend.

- `EditorCancelListener`: for editor cancel events, which corresponds to the `cancelEditing()` method call.

- `EditorOpenListener` / `EditorCloseListener`: for editor open and close events.

The component to use as input to edit each item property value can be customized using the `editorComponent(…​)` builder method.

The row editor provides a buffered mode: when enabled, the edited values are setted into the item instance only when the `saveEditingItem()` method is called, for example using a provided save button. The `editorBuffered` builder method can be used to enable or disable the buffered mode.

    PropertyListing.builder(SUBJECT) //
        .editable() (1)
        .editorBuffered(true) (2)
        .withComponentColumn(item -> Components.button("Edit", e -> listing.editItem(item)) (3)
        ).editorComponent(new Div( (4)
            Components.button("Save", e -> listing.saveEditingItem()),
            Components.button("Cancel", e -> listing.cancelEditing())))
        .displayAsFirst() (5)
        .add() (6)
        .withEditorSaveListener(event -> { (7)
          PropertyBox item = event.getItem(); (8)
          /* update the item in backend */
        }).build();

1 | Enable the editable mode
2 | Set the editor in buffered mode
3 | Add a new column to provide the `Edit` button for each row, using the `editItem` method to edit the current row item
4 | Set the editor component for the added column: it will be displayed when the row is in edit mode, providing the `Save` and `Cancel` buttons, which invoke the `saveEditingItem()` and the `cancelEditing()` methods respectively
5 | Configure the added column to be displayed as first column
6 | Add the column to the listing
7 | Add an editor save listener to update the item data in backend
8 | The save event provides the edited item instance

##### Default editor components and customization

By default, when a row is turned into edit mode, the Holon PropertyRenderer architecture is used to obtain an `Input` type component for each item property to edit (See Input components and forms for information on the `Input` component API).

| See the Property renderering documentation for details about the property renderers architecture.

The editor component for a listing item property (and so for a listing column), can be configured using the following builder methods:

- `editor`: to set a `Input` as editor component. See Input components and forms.

- `editorField`: to use a standard Vaadin `HasValue` component as editor component.

- `editorComponent`: to use generic `Component` as editor component.

    PropertyListing.builder(SUBJECT) //
        .editor(NAME, Input.string().build()) (1)
        .editor(NAME, property -> Input.string().build()) (2)
        .editor(ID, Input.string().build(), new StringToLongConverter("")) (3)
        .editorField(NAME, new TextField()) (4)
        .editorField(ID, new TextField(), new StringToLongConverter("")) (5)
        .editorComponent(ID, new Button()) (6)
        .build();

1 | Set the editor `Input` to use for the `NAME` property/column
2 | Set the editor `Input` to use for the `NAME` property/column
3 | Set the editor `Input` to use for the `ID` property/column, providing a `Long` to `String` and back converter
4 | Set the editor `HasValue` component to use for the `NAME` property/column
5 | Set the editor `HasValue` component to use for the `ID` property/column, providing a `Long` to `String` and back converter
6 | Set a generic component as `ID` property/column editor component

Since the `PropertyRenderer` based architecture is used to obtain the editor components by default using the `Input` rendering type, the editor component can customized also by adding a new `PropertyRenderer` for a property definition. This ensures consistency across the application, and can be used to automatically configure the editor components for any item listing instance.

    PropertyRendererRegistry.getDefault().forProperty(NAME, (1)
        InputPropertyRenderer.create(property -> Input.stringArea().build()));

    PropertyListing.builder(SUBJECT).editable().build(); (2)

1 | Add a new `PropertyRenderer` to the default registry to render the `NAME` property using the provided stringArea type `Input` component.
2 | Any item listing which includes the `NAME` property will use the registered renderer to obtain the `Input` component to use as the `NAME` property/column editor

##### Data validation

To validate the user input when a listing row is in edit mode, the standard Holon Validator API can be used.

When the editor save action is performed (using the `saveEditingItem()` item listing API method), all the registered validators are invoked and the save operation is interrupted if one ore more validators fails, notifying the validation errors to the user.

1. Property level validators:

One or more validators can be bound to an item property to perform the property value validation. The property value validation is performed when the user leaves an editor component and when the editor save action in invoked.

Any validator bound to a property at property definition time are automatically inherited as item property value validators.

New validators can be added to an item property using the `withValidator` item listing builder method.

    final StringProperty NAME = StringProperty.create("name").withValidator(Validator.notBlank()); (1)

    PropertyListing.builder(SUBJECT) //
        .withValidator(NAME, Validator.max(10)) (2)
        .build();

1 | The notBlank validator is added to the `NAME` property at definition time, so it will be inherited from the item listing editor validation
2 | A max validator is added to the `NAME` property to ensure the String value is maximum 10 characters long

2. Row level validators:

One or more row level validators can be added to an item listing using the `withValidator` builder method. The row level validators are invoked when the editor save action is performed, and the current item state s provided to validators to perform the required checks.

    PropertyListing.builder(SUBJECT) //
        .withValidator(Validator.create(item -> item.getValue(ID) != null, "Id value must be not null")) (1)
        .build();

1 | Add a row level validator

##### Validation status handler

By default, the validation errors originated by the registered validators are notified to the user in the following way:

- For property level validators, if the editor component supports error messages notification (using the Vaadin `HasValidation` interface), the validation errors are setted as component errors.

- For row level validators, a Dialog is used to notify the validation errors.

The validation status errors notification can be customized using the ValidationStatusHandler interface, both at property and row level.

The `ValidationStatusHandler` validation event provides the validation status (valid, invalid or unresolved) and the current validation errors, if any.

To customize both the property level and the row level validation status notification, the `validationStatusHandler` builder method can be used.

    PropertyListing.builder(SUBJECT) //
        .validationStatusHandler(event -> { (1)
          if (event.isInvalid()) {
            Notification.show("Validation falied: " + event.getErrorMessage());
          }
        }).validationStatusHandler(NAME, event -> { (2)
          /* omitted */
        }).build();

1 | Set a custom row level validation status handler
2 | Set a custom property level validation status handler for the `NAME` property

Furthermore, the GroupValidationStatusHandler interface can be used to override all the validation status notification, customizing both the property level and the row level validation status notification using a single handler.

    PropertyListing.builder(SUBJECT) //
        .groupValidationStatusHandler(event -> { (1)
          event.getGroupStatus(); (2)
          event.getInputsValidationStatus(); (3)
          event.getGroupErrorMessages(); (4)
          event.getInputsValidationStatus().forEach(s -> s.getErrorMessages()); (5)
        }).build();

1 | Set the `GroupValidationStatusHandler` for the row editor
2 | Get the row-level validation status
3 | Get the single editor components validation status
4 | Get the row-level validation errors
5 | Get the single editor components validation errors

##### Listening to editor components value change

When a listing row is in edit mode, one ore more `ValueChangeListener` can be added to the editor input components to listen to value change, using the `withValueChangeListener` builder method.

    PropertyListing.builder(SUBJECT) //
        .withValueChangeListener(NAME, event -> { (1)
          event.getOldValue();
          event.getValue();
        }).build();

1 | Add a value change listener for the `NAME` property

### 3.8. View components and forms

The ViewComponent component can be used to display data, providing consistent formatting and style across the whole UI, including localization and internationalization support.

The `ViewComponent` API extends:

- `ValueHolder`: it handles a typed value. See The `ValueHolder` interface.

- `HasComponent`: it can used as UI component. See The `HasComponent` interface.

A `ViewComponent` instance can be created either using the `ViewComponent` API builder methods, providing the value type or the `Components` API, through the `Components.view` sub interface (see Component builders and providers).

The `ViewComponent` builder API provides methods to configure the UI component, including methods to set a localizable label for the component and to add component click listeners.

    ViewComponent<String> viewComponent = ViewComponent.builder(String.class) (1)
        .fullWidth() (2)
        .styleName("my-style") (3)
        .label("My label") (4)
        .label("My label", "label.message.code") (5)
        .description("My description") (6)
        .onClick(event -> { (7)
          /* handle the click event */
        }).withValue("Initial value") (8)
        .withValueChangeListener(event -> { (9)
          String oldValue = event.getOldValue(); (10)
          String newValue = event.getValue(); (11)
        }).build();

    viewComponent = ViewComponent.create(String.class); (12)

    viewComponent = Components.view.component(String.class) (13)
        /* configuration omitted */
        .build();

1 | Get a `String` type `ViewComponent` builder
2 | Set the component width to 100%
3 | Add a CSS style class name
4 | Set the label
5 | Set the label using a localizable message
6 | Set the description
7 | Add a click handler
8 | Set an initial value
9 | Add value change listener
10 | The previous value
11 | The changed value
12 | Direct `ViewComponent` creation method
13 | The `Components.view.component` method of the `Components` API can be used to create and configure a `ViewComponent`

A `ViewComponent` instance can be used as value holder to handle the value to display (see The `ValueHolder` interface).

    ViewComponent<String> viewComponent = ViewComponent.create(String.class); (1)

    new VerticalLayout().add(viewComponent.getComponent()); (2)

    viewComponent.setValue("My value"); (3)
    String value = viewComponent.getValue(); (4)
    value = viewComponent.getValueIfPresent().orElse("Default value"); (5)

    viewComponent.clear(); (6)
    boolean empty = viewComponent.isEmpty(); (7)

1 | Create a `String` type `ViewComponent`
2 | Add the component to a layout using the `getComponent()` method
3 | Set the component value
4 | Get the component value
5 | Get the component optional value
6 | Clear the component value
7 | Check if the component is empty

#### 3.8.1. Value conversion and formatting

A `ViewComponent` converts the value it holds to a `String` in order to display it in UI. For value conversion and formatting the `ViewComponent` API relies on the Holon Platform StringValuePresenter API.

This ensures a consistent behaviour across the application on how the values are displayed and the current `LocalizationContext` is used, if available, to apply the proper internationalization conventions to format, for example, a numeric value.

See the StringValuePresenter API documentation for details.

To provide a custom value conversion logic, a value conversion function can be provided at `ViewComponent` build time:

    ViewComponent<Integer> viewComponent = ViewComponent.<Integer>builder(value -> String.valueOf(value)).build(); (1)

1 | Create a `Integer` type `ViewComponent`, providing the function to convert the `Integer` value to `String`

#### 3.8.2. Using the property value presenters

When a `Property` value has to be displayed, a `ViewComponent` can be created and bound to the `Property` definition, inheriting the property value type as component type and enabling the PropertyValuePresenter based strategy to convert and format the value in a consistent way across the application.

| See the Property value presentation documentation for details on property value presentation.

    NumericProperty<Integer> MY_PROPERTY = NumericProperty.integerType("my_property"); (1)

    ViewComponent<Integer> viewComponent = ViewComponent.create(MY_PROPERTY); (2)

1 | `Integer` type property definition
2 | Create a `ViewComponent` using the `MY_PROPERTY` property definition. The property value presenters will be used to convert the value to a `String` and apply formatting

This allows to generalize the property value presentation and make it consistent across all the application UI components which support property value presenters, including `Input` components (see Input components and forms) and listing components (see List data in grids).

New `PropertyValuePresenter` can be registered and used transparently to present the value for a specific type or a specific property configuration.

For example, suppose we want to add a `#` prefix to each value of the `MY_PROPERTY` property. We can declare a `PropertyValuePresenter` and bind it to the `MY_PROPERTY` property in the property presenters registry:

    PropertyValuePresenterRegistry.getDefault() (1)
        .forProperty(MY_PROPERTY, (property, value) -> "#" + value); (2)

1 | Get the default `PropertyValuePresenterRegistry`
2 | Register a `PropertyValuePresenter`, bound to the `MY_PROPERTY` property, which adds a `#` prefix to the property value

From now on, any `ViewComponent` instance will use the new presenter to render the `MY_PROPERTY` property value.

    ViewComponent<Integer> viewComponent = ViewComponent.create(MY_PROPERTY); (1)

    String value = MY_PROPERTY.present(1); (2)

1 | The `ViewComponent` instance will use the new presenter to render the `MY_PROPERTY` property value
2 | Any other property presentation service will use the new presenter for the `MY_PROPERTY` property value. In this example, the `MY_PROPERTY` property is directly used to present the `1` value and the result will be the String `#1`.

#### 3.8.3. Create a `ViewComponent` from a generic `Component`

You can use the `ViewComponent` API `adapt` static methods to transform any `Component` into a `ViewComponent`. The `Component` will be used as `ViewComponent` content and a suitable function must be provided to setup the `Component` instance each time the value changes, for example to display the value using the custom `Component` instance.

A generic `Component` can be turn into a `ViewComponent` either providing:

1. The `Component` to use a `ViewComponent` content and a consumer function to setup the `Component` instance each time the value changes:

    ViewComponent<String> viewComponent = ViewComponent.adapt(String.class, new Span(), (span, value) -> {
      span.setText(value);
    }).build(); (1)

1 | A `Span` is used as `String` type `ViewComponent` content, setting the Span text with the provided value each time the `ViewComponent` value changes

2. A function to provided a custom `Component` instance each time the value changes, to be used as `ViewComponent` content:

    ViewComponent<String> viewComponent = ViewComponent.adapt(String.class, value -> {
      if (value != null) {
        return new RouterLink(value, MyView.class, value); (1)
      }
      return null;
    }).build();

1 | Each time the value changes, a new `RouterLink` is created and used as `ViewComponent` content

The `adapt` methods return a builder API consistent with the default `ViewComponent` builder API, allowing to configure the `ViewComponent` component.

    ViewComponent<String> viewComponent = ViewComponent.adapt(String.class, value -> {
      if (value != null) {
        return new RouterLink(value, MyView.class, value); (1)
      }
      return null;
    }) (1)
        .fullWidth() (2)
        .styleName("my-style") (3)
        .label("My label") (4)
        .label("My label", "label.message.code") (5)
        .description("My description") (6)
        .onClick(event -> { (7)
          /* handle the click event */
        }).withValue("Initial value") (8)
        .withValueChangeListener(event -> { (9)
          String oldValue = event.getOldValue();
          String newValue = event.getValue();
        }).build();

1 | Create a `ViewComponent` which shows a `RouterLink` each time the value changes
2 | Set the component width to 100%
3 | Add a CSS style class name
4 | Set the label
5 | Set the label using a localizable message
6 | Set the description
7 | Add a click handler
8 | Set an initial value
9 | Add value change listener

#### 3.8.4. `ViewComponent` property renderer

When the `holon-vaadin-flow` artifact is in classpath, a default `PropertyRenderer` is automatically registered to render a `Property` as a `ViewComponent`.

| See the Property renderering documentation for details about the property renderers architecture.

So the `ViewComponent.class` type can be used to render any property as a `ViewComponent`. In this scenario, the property localizable message is used if available as `ViewComponent` label.

    BooleanProperty PROPERTY = BooleanProperty.create("test") (1)
        .message("caption").messageCode("caption.message.code"); (2)

    ViewComponent<Boolean> viewComponent = PROPERTY.render(ViewComponent.class); (3)

1 | Declare a boolean type property
2 | Set the property localizable message
3 | Create `ViewComponent` instance using the property renderer. The property localizable message will be used as `ViewComponent` label.

#### 3.8.5. Organize view components in groups and forms

A set of `ViewComponent` type components can be grouped and organized using a PropertyViewGroup, using the Holon Platform Property model to bind each `ViewComponent` to a property definition.

The property definitions will be used as references to get and configure the `ViewComponent` instances managed by the group and to set the group values to display using a `PropertyBox` type.

The `PropertyViewGroup` API provides method to inspect the available properties and the `ViewComponent` instances bound to each property. Through the `ValueHolder` API, the group value can be setted and managed (see The `ValueHolder` interface).

To create a `PropertyViewGroup`, the property set to use must be provided at build time. Both the `PropertyViewGroup` API and the `Components` API (through the `Components.view` sub interface) can be used to obtain a property view group builder.

By default, the property rendering architecture is used to automatically generate the `ViewComponent` instances for each property of the group property set (see `ViewComponent` property renderer).

For example, given the following property model definition:

    static final NumericProperty<Long> ID = NumericProperty.longType("id");
    static final StringProperty NAME = StringProperty.create("name");
    static final PropertySet<?> SUBJECT = PropertySet.of(ID, NAME);

A `PropertyViewGroup` can be created in the following way:

    PropertyViewGroup group = PropertyViewGroup.builder(SUBJECT).build(); (1)
    group = Components.view.propertyGroup(SUBJECT).build(); (2)

    Collection<Property<?>> properties = group.getProperties(); (3)
    Stream<ViewComponent<?>> components = group.getElements(); (4)
    group.getBindings().forEach(binding -> { (5)
      Property<?> property = binding.getProperty();
      ViewComponent<?> component = binding.getElement();
    });

    Optional<ViewComponent<?>> element = group.getElement(NAME); (6)
    ViewComponent<?> component = group.requireElement(NAME); (7)

    PropertyBox value = PropertyBox.builder(SUBJECT).set(ID, 1L).set(NAME, "One").build();

    group.setValue(value); (8)
    value = group.getValue(); (9)

    group.clear(); (10)
    group.isEmpty(); (11)

1 | Create a `PropertyViewGroup` using the `SUBJECT` property set. The `ViewComponent` for each property will be automatically generated using the property renderers
2 | Create a `PropertyViewGroup` from the `Components` API
3 | Get the group property set
4 | Get the group `ViewComponent` elements
5 | Get the group bindings, i.e. the `ViewComponent` bound to each property
6 | Get the `ViewComponent` bound to the `NAME` property, if available
7 | Require the `ViewComponent` bound to the `NAME` property
8 | Set the group value using a `PropertyBox`: each property value available from the `PropertyBox` instance will be setted into the corresponding `ViewComponent`, if available
9 | Get the current group value
10 | Clear the group value
11 | Check whether the group is empty, i.e. has no value

To customize this behaviour and provide the `ViewComponent` to use for one or more property, the `PropertyViewGroup` builder API provides a set of `bind` methods, which can be use to explicitly bind a `ViewComponent` instance to a property.

    PropertyViewGroup group = PropertyViewGroup.builder(SUBJECT) (1)
        .bind(NAME, ViewComponent.create(String.class)) (2)
        .bind(NAME, property -> ViewComponent.create(String.class)) (3)
        .build();

1 | Create a `PropertyViewGroup` using the `SUBJECT` property set
2 | Bind a `ViewComponent` instance to the `NAME` property
3 | Bind a `ViewComponent` instance to the `NAME` property using a function

##### Group configuration

The `PropertyViewGroup` builder API provides method to configure the group, allowing to:

- Hide one or more property: the hidden property won’t be bound to a `ViewComponent`

- Add a post processor to configure the `ViewComponent` instances just before the binding occurs

- Add group value change listeners

    PropertyViewGroup group = PropertyViewGroup.builder(SUBJECT) (1)
        .hidden(ID) (2)
        .withPostProcessor((property, component) -> { (3)
          /* ViewComponent configuration */
          component.hasStyle().ifPresent(s -> s.addClassName("my-style"));
        }) //
        .withValueChangeListener(event -> { (4)
          /* handle value change */
          PropertyBox value = event.getValue();
        }).build();

1 | Create a `PropertyViewGroup` using the `SUBJECT` property set
2 | Set the `ID` property as hidden
3 | Add a binding post processor
4 | Add a value change listener

##### Using a `PropertyViewForm` to make the group a UI component

The `PropertyViewGroup` API handles a group of view components bound to a property set, but is it not a UI component itself. The PropertyViewForm API can be used to provide a UI component for the group and use it as a form in application UI.

A `PropertyViewGroup` extends the `HasComponent` interface to provide the actual group UI component (see The `HasComponent` interface) and the Composable API to declare the UI component to use as group elements container and the strategy to apply to organize the `ViewComponent` group elements into the group content area.

The `Composer` API can be used to implement the composition logic, i.e. to add the available `ViewComponent` elements to the UI component declared as group content. The `Composer` function provides:

- The group UI content element.

- A reference to the group API to obtain the `ViewComponent` elements (and the corresponding property bindings) to add to the group UI content element.

A default `Composer` for a `com.vaadin.flow.component.HasComponents` type UI element can be obtain using the `componentContainerComposer()` method of the `Composable` API. This composer adds the group elements sequentially to the `HasComponents` group content element, in the order they are provided from the group property set.

    PropertyViewForm form = PropertyViewForm.builder(new VerticalLayout(), SUBJECT) (1)
        .composer(Composable.componentContainerComposer()) (2)
        .build();

    myLayout.add(form.getComponent()); (3)

    form.setValue(PropertyBox.builder(SUBJECT).set(ID, 1L).set(NAME, "One").build()); (4)

1 | Create a `PropertyViewForm` using the `SUBJECT` property set, a `VerticalLayout` as group UI element
2 | The default component container composer is used
3 | The `getComponent()` method can be used to add the `PropertyViewForm` to a layout
4 | Set a form value

A set of convenience builder methods are available for the base Vaadin layouts:

    PropertyViewForm form = PropertyViewForm.verticalLayout(SUBJECT).build(); (1)
    form = PropertyViewForm.horizontalLayout(SUBJECT).build(); (2)
    form = PropertyViewForm.formLayout(SUBJECT).build(); (3)

    // Using the Components API:
    form = Components.view.formVertical(SUBJECT).build();
    form = Components.view.formHorizontal(SUBJECT).build();
    form = Components.view.form(SUBJECT).build();

1 | Create a `PropertyViewForm` using the `SUBJECT` property set and a `VerticalLayout` as group UI element
2 | Create a `PropertyViewForm` using the `SUBJECT` property set and a `HorizontalLayout` as group UI element
3 | Create a `PropertyViewForm` using the `SUBJECT` property set and a `FormLayout` as group UI element

A custom `Composer` can be used to control and customize the group element composition strategy:

    PropertyViewForm form = PropertyViewForm.verticalLayout(SUBJECT) //
        .composer((content, group) -> { (1)
          group.getBindings().forEach(binding -> {
            content.add(binding.getElement().getComponent());
          });
        }).build();

1 | Provide a custom composition logic

##### Form configuration

A `PropertyViewForm` can be configured using the builder API in order to:

- Hide one or more property: the hidden property won’t be bound to a `ViewComponent`

- Add an initializer to configure the form UI content

- Add a post processor to configure the `ViewComponent` instances just before the binding occurs

- Add form value change listeners

- Configure the property captions, i.e. to set the label to use for the `ViewComponent` bound to a property

    PropertyViewForm.formLayout(SUBJECT) (1)
        .hidden(ID) (2)
        .initializer(content -> { (3)
          /* content configuration */
          FormLayout fl = content;
        }).withPostProcessor((property, component) -> { (4)
          /* ViewComponent configuration */
          component.hasStyle().ifPresent(s -> s.addClassName("my-style"));
        }) //
        .withValueChangeListener(event -> { (5)
          /* handle value change */
          PropertyBox value = event.getValue();
        }) //
        .hidePropertyCaption(ID) (6)
        .propertyCaption(NAME, "My name", "name.message.code") (7)
        .build();

1 | Create a `PropertyViewForm` using the `SUBJECT` property set and a `FormLayout`
2 | Set the `ID` property as hidden
3 | Set the form content initializer
4 | Set the binding post processor
5 | Add a value change listener
6 | Hide the `ID` property caption
7 | Set the localizable caption for the `NAME` property

### 3.9. Input components and forms

The Input API can be used to create UI components to handle user input, ensuring a consistent data type handling and input format patterns.

The `Input` API extends:

- `ValueHolder`: it handles a typed value. See The `ValueHolder` interface.

- `HasComponent`: it can used as UI component. See The `HasComponent` interface.

Furthermore, the `Input` API provides methods to set the UI component in read only mode and to display required indicators and validation errors.

A `Input` instance can be created either using the `Input` API builder methods, providing the value type, or the `Components` API, through the `Components.input` sub interface (see Component builders and providers).

The `Input` builder API provides methods to configure the UI component, including methods to set a localizable label for the component and a complete set of configuration methods according to the input value type.

    Input<String> input = Input.string() (1)
        .fullWidth() (2)
        .styleName("my-style") (3)
        .label("My label") (4)
        .label("My label", "label.message.code") (5)
        .description("My description") (6)
        .blankValuesAsNull(true) (7)
        .autocapitalize(Autocapitalize.WORDS) (8)
        .maxLength(50) (9)
        .placeholder("My placeholder", "placeholder.message.code")(10)
        .autofocus(true)(11)
        .prefixComponent(new Button("Prefix"))(12)
        .tabIndex(99) (13)
        .readOnly() (14)
        .withBlurListener(event -> {(15)
          /* handle blur event */
        }).withValueChangeListener(event -> { (16)
          String oldValue = event.getOldValue(); (17)
          String newValue = event.getValue(); (18)
        }).build();

    input = Components.input.string() (13)
        /* configuration omitted */
        .build();

1 | Get a `String` type `Input` builder
2 | Set the width to 100%
3 | Add a CSS style class name
4 | Set the input label
5 | Set the input label using a localizable message
6 | Set the input description
7 | Set to treat blank values as `null` values.
8 | Set the auto-capitalize mode
9 | Set the max characters count allowed for input
10 | Set the input placeholder using a localizable message
11 | Enable auto focus
12 | Set the prefix component
13 | Set the input tab index
14 | Set the input as read only, preventing the user from changing the input value
15 | Add a blur (focus lost) listener
16 | Add value change listener
17 | The previous value
18 | The changed value

A set of `Input` builders for the most common types are available both form the `Input` API and from the `Components.input` API.

Each `Input` is rendered using a suitable UI component according to the input value type. For example, a `TextField` is used for String type inputs and a `Checkbox` for boolean type inputs.

    Input<String> input1 = Input.string().build(); (1)
    Input<String> input2 = Input.stringArea().build(); (2)
    Input<Boolean> input3 = Input.boolean_().build(); (3)
    Input<Double> input4 = Input.number(Double.class).build(); (4)
    Input<LocalDate> input5 = Input.localDate().build(); (5)
    Input<LocalDateTime> input6 = Input.localDateTime().build(); (6)
    Input<LocalTime> input7 = Input.localTime().build(); (7)
    Input<Date> input8 = Input.date().build(); (8)

    Optional<Input<String>> input = Input.create(String.class); (9)

1 | Create an `Input` for `String` type values
2 | Create an `Input` for `String` type values using a text area to render the input component
3 | Create an `Input` for `Boolean` type values
4 | Create an `Input` for a numeric type value, a `Double` in this case
5 | Create an `Input` for `LocalDate` type values
6 | Create an `Input` for `LocalDateTime` type values
7 | Create an `Input` for `LocalTime` type values
8 | Create an `Input` for `Date` type values
9 | Create an `Input` for the given value type, if a suitable implementation is available

| The `Components.input` API provides the same methods to obtain the input builders.

A `Input` instance can be used as value holder to handle the input value (see The `ValueHolder` interface).

    Input<String> input = Input.string().build(); (1)

    myLayout.add(input.getComponent()); (2)

    input.setValue("My value"); (3)
    String value = input.getValue(); (4)
    value = input.getValueIfPresent().orElse("Default value"); (5)

    input.clear(); (6)
    boolean empty = input.isEmpty(); (7)

    input.setReadOnly(true); (8)
    input.isReadOnly(); (9)

    input.addValueChangeListener(event -> { (10)
      /* handle value change */
    });

1 | Create a `String` type `Input`
2 | Add the input component to a layout using the `getComponent()` method
3 | Set the input value
4 | Get the input value
5 | Get the input optional value
6 | Clear the input value
7 | Check if the input is empty (i.e. has no value)
8 | Set the input as read only
9 | Check whether the input is read only
10 | Add a value change listener

#### 3.9.1. `Input` property renderer

When the `holon-vaadin-flow` artifact is in classpath, a default `PropertyRenderer` is automatically registered to render a `Property` as an `Input`.

| See the Property renderering documentation for details about the property renderers architecture.

So the `Input.class` type can be used to render any property as a `Input`. In this scenario, the property localizable message is used if available as `Input` label.

The `Input` API makes available the `create(Property<T> property)` method to directly create an `Input` for a given property.

    NumericProperty<Integer> MY_PROPERTY = NumericProperty.integerType("my_property"); (1)

    Input<Integer> input = Input.create(MY_PROPERTY); (2)

    Input<Integer> viewComponent = MY_PROPERTY.render(Input.class); (3)

1 | Declare a `Integer` type property
2 | Create a `Input` to handle the `MY_PROPERTY` property value using the `Input` API
3 | Create a `Input` to handle the `MY_PROPERTY` property value using the property renderer for the `Input` class

The property renderers architecture is used consistently across the application UI, so when a renderer is bound to a specific property condition it is used by all the UI components with property rendering support, including input groups/forms (see Organize `Input` components in groups and forms) and item listing editors (see Editing the listing items).

For example, suppose we want to use a custom `MyInput` class to render the `Input` component for the `MY_PROPERTY` property definition. A custom property renderer can be created and registered:

    PropertyRendererRegistry.getDefault() (1)
        .forProperty(MY_PROPERTY, InputPropertyRenderer.create(property -> new MyInput())); (2)

1 | Get the default `PropertyRendererRegistry`
2 | Register a `InputPropertyRenderer`, bound to the `MY_PROPERTY` property, to provide a `MyInput` instance

From now on, the `Input` component for the `MY_PROPERTY` property definition will be a `MyInput` instance.

#### 3.9.2. Input value conversion

The `Input` API provides methods to use an `Input` with a different type than the value type to handle, providing a suitable `com.vaadin.flow.data.converter.Converter` to perform the value conversions to the required type.

    Input<String> stringInput = Input.string().build(); (1)
    Input<Integer> integerInput = Input.from(stringInput, new StringToIntegerConverter("Conversion failed")); (2)

1 | Create a `String` type `Input`
2 | Create a `Integer` type `Input` from the previous one, providing the String to Integer and back converter

A Holon Platform `PropertyValueConverter` can also be use to provide the value conversion logic when the input is bound to a `Property` definition.

    BooleanProperty PROPERTY = BooleanProperty.create("test");

    Input<Integer> integerInput = Input.number(Integer.class).build(); (1)
    Input<Boolean> booleanInput = Input.from(integerInput, PROPERTY,
        PropertyValueConverter.numericBoolean(Integer.class)); (2)

1 | Create a `Integer` type `Input`
2 | Create a `Boolean` type `Input` for the `PROPERTY` property, using the previous input and a numeric boolean `PropertyValueConverter`

#### 3.9.3. Input adapters for `HasValue` components

The `Input` API provides methods to adapt a standard Vaadin `HasValue` type input component as an `Input`, including value conversion support using a `com.vaadin.flow.data.converter.Converter`.

    Input<String> stringInput = Input.builder(new TextField()).build(); (1)

    Input<Integer> input = Input.from(new TextField(), new StringToIntegerConverter("Conversion failed")); (2)

1 | Create a `String` type `Input` from a `TextField`
2 | Create a `Integer` type `Input` from a `TextField`, providing the value converter

#### 3.9.4. Select type inputs

The SingleSelect and MultiSelect APIs are `Input` extensions which represent selectable input components, i.e. input components which provide a set of items from which the input value can be selected, either supporting single or multiple selection values.

The `Input` API and the corresponding Components.input API provides methods to create `SingleSelect` and `MultiSelect` type input components, providing the selectable value type.

For `SingleSelect` input types, the input component can be rendered as:

- Simple select: a Vaadin `Select` component is used as input component.

- Filterable select: a Vaadin `ComboBox` component is used as input component.

- Options select: a `RadioButtonGroup` component is used as input component.

    SingleSelect<String> singleSelect = Input.singleSelect(String.class).build(); (1)
    singleSelect = Input.singleOptionSelect(String.class).build(); (2)

    MultiSelect<String> multiSelect = Input.multiOptionSelect(String.class).build(); (3)

1 | Create a `String` type `SingleSelect` input
2 | Create a `String` type `SingleSelect` input using the options rendering mode
3 | Create a `String` type `MultiSelect` input

The select input components can be used just like any other value holder type component to set and get the selected item/s (see The `ValueHolder` interface). The `MultiSelect` type input, since it allows multiple items selection, uses a `java.util.Set` to handle the input value.

| The `Components.input` API provides the same methods to obtain the select type input builders.

    SingleSelect<String> singleSelect = Input.singleSelect(String.class).build();

    singleSelect.setValue("A value"); (1)
    String value = singleSelect.getValue(); (2)
    singleSelect.clear(); (3)
    singleSelect.isEmpty(); (4)

    MultiSelect<String> multiSelect = Input.multiOptionSelect(String.class).build();

    multiSelect.setValue(Arrays.asList("Value 1", "Value 2").stream().collect(Collectors.toSet())); (5)
    Set<String> values = multiSelect.getValue(); (6)

1 | Set the input value, i.e. select the given value
2 | Get the input (selected) value
3 | Clear the input value (deselect any value)
4 | Check whether the input is empyt (no value is selected)
5 | Set the input values, i.e. select the given values, using a `Set`
6 | Get the input (selected) values as a `Set`

Besides the `Input` API, the selectable inputs implements the Selectable API, which allows to manage and obtain the selected items.

    SingleSelect<String> singleSelect = Input.singleSelect(String.class).build();

    singleSelect.select("A value"); (1)
    String value = singleSelect.getSelectedItem().orElse(null); (2)
    singleSelect.deselectAll(); (3)

1 | Select given value
2 | Get the selected value
3 | Deselect any value

##### Select items data source

A select type `Input`, whether it’s a `SingleSelect` or a `MultiSelect`, requires an item set to be configured, which represents the source for the selectable values. Only the available items will be used as valid selectable input values.

The builder API provides the `items` and `addItem` methods to provides the selection items set.

    SingleSelect<String> singleSelect = Input.singleSelect(String.class) //
        .addItem("Value 1") (1)
        .addItem("Value 2") (2)
        .items("Value 1", "Value 2") (3)
        .build();

1 | Add a selection item
2 | Add another selection item
3 | Set the selection items, replacing any previous item set

A standard Vaadin `DataProvider` can be used as items data source.

    SingleSelect<String> singleSelect = Input.singleSelect(String.class) //
        .dataSource(DataProvider.ofItems("Value 1", "Value 2")) (1)
        .build();

1 | Use a `DataProvider` as items data source

When the item type does not match the selection value type, a ItemConverter con be used to provide the item to selection value and back conversion logic.

    SingleSelect<String> singleSelect = Input.singleSelect(String.class, MyBean.class, ItemConverter.create( (1)
        item -> item.getName(), (2)
        value -> Optional.of(new MyBean(value)) (3)
    )).addItem(new MyBean("One")).addItem(new MyBean("Two")).build();

1 | Create a `String` type `SingleSelect` which uses a `MyBean` class as items type, providing a suitable `ItemConverter`
2 | Convert a `MyBean` type item into a `String` type selection value
3 | Convert a `String` type selection value into a `MyBean` type item

##### Use the `Datastore` API as items data source

When the property model is used to build a select type input, the selection items are represented using the `PropertyBox` type by default, and the property which represents the selection value has to be declared a construction time.

The select input type will match the selection property type and the value provided as selection value will be obtained using the selection property definition from the `PropertyBox` type item instances.

For example, given the following property model definition:

    static final NumericProperty<Long> ID = NumericProperty.longType("id");
    static final StringProperty NAME = StringProperty.create("name");
    static final PropertySet<?> SUBJECT = PropertySet.of(ID, NAME);

A `SingleSelect` to select the `ID` property can be created as follows:

    SingleSelect<Long> singleSelect = Input.singleSelect(ID) (1)
        .addItem(PropertyBox.builder(SUBJECT).set(ID, 1L).set(NAME, "One").build()) (2)
        .build();

1 | Create a `SingleSelect` using the `ID` property as selection property: the select input type will be `Long` like the property type
2 | Add a `PropertyBox` type selection item

When a property model bound select is used, the most simple and powerful way to provided the selection items is to use a `Datastore` as data source. The `Datastore` API makes easy and straightful to bind the select input to a backend data source.

When a `Datastore` is used, a `DataTarget` definition is required to declare the data model entity to use as items data source (for example a RDBMS table name, or a collection name in a document based database).

A `Datastore` based data source can be configured using a standard DataProvider, through the `DatastoreDataProvider` API: see the Datastore API integration section to learn how to create and configure a `Datastore` based `DataProvider`.

Furthermore, the select input builder APIs provides convenience methods to set and configure a data source using a `Datastore`.

By default, only the selection property is used as items property set. To specify a different property set (i.e. a different query projection), the property set must be provided at data source configuration time.

For example, given the following `DataTarget` definition;

    static final DataTarget<?> TARGET = DataTarget.named("subjects");

The select of the previous example can be configured as follows:

    Datastore datastore = getDatastore();

    SingleSelect<Long> singleSelect = Input.singleSelect(ID) (1)
        .dataSource(datastore, TARGET) (2)
        .build();

    singleSelect = Input.singleSelect(ID) //
        .dataSource(datastore, TARGET, SUBJECT) (3)
        .build();

1 | Create a `SingleSelect` using the `ID` property as selection property
2 | Use a `Datastore` as items data source, providing the `DataTarget` to use
3 | Declare to use the `SUBJECT` property set as items property set (hence as query projection)

The `Datastore` based data source can be configured, for example to add query filters and sorts. The configuration methods provided by the builder API corresponds to the ones provided by the `DatastoreDataProvider` API. See `Datastore` Query configuration for details.

    SingleSelect<Long> singleSelect = Input.singleSelect(ID) (1)
        .dataSource(getDatastore(), TARGET, SUBJECT) (2)
        .withQueryFilter(NAME.isNotNull()) (3)
        .withQuerySort(ID.asc()) (4)
        .withQueryConfigurationProvider(myQueryConfigurationProvider) (5)
        .build();

1 | Create a `SingleSelect` using the `ID` property as selection property
2 | Use a `Datastore` as items data source, providing the `DataTarget` to use
3 | Add a fixed query filter
4 | Add a fixed query sort
5 | Add a `QueryConfigurationProvider` reference to provide dynamic query filters and sorts

##### Filterable select inputs

When a `SingleSelect` in the filterable select mode is used, since it is rendered using a `ComboBox` component, the selection items to select can be suggested by the input component, using the user input to filter the items set.

When a standard `DataProvider` is used, the `filteringBy*` methods can be used to provide the items filtering strategy.

    SingleSelect<String> input = Input.singleSelect(String.class) (1)
        .dataSource(DataProvider.ofCollection(Arrays.asList("One", "Two", "Three")) (2)
            .filteringByPrefix(v -> v)) (3)
        .build();

1 | Create a `String` type `SingleSelect`
2 | Use a `DataProvider` as items data source
3 | Set the filtering mode, in this case checking whether the item value starts with the query value

When a `Datastore` based data source is used (see Use the `Datastore` API as items data source), a function can be configured to transform the text typed by the user into the `QueryFilter` to add to the Datastore query to filter the returned items.

The filter converter function can be configured either using:

1. The `dataSource` builder method version which accepts the filter converter function:

    SingleSelect<Long> singleSelect = Input.singleSelect(ID) (1)
        .dataSource(getDatastore(), TARGET, (2)
            text -> NAME.contains(text), (3)
            SUBJECT (4)
        ).build();

1 | Create a `SingleSelect` using the `ID` property as selection property
2 | Use a `Datastore` as items data source, providing the `DataTarget` to use
3 | Provide the function to convert the user typed text value to a `QueryFilter`
4 | Use the `SUBJECT` property set as items property set

1. The `filterConverter` builder method:

    SingleSelect<Long> singleSelect = Input.singleSelect(ID) (1)
        .dataSource(getDatastore(), TARGET, SUBJECT) (2)
        .filterConverter(text -> NAME.contains(text)) (3)
        .build();

1 | Create a `SingleSelect` using the `ID` property as selection property
2 | Use a `Datastore` as items data source, providing the `DataTarget` to use and `SUBJECT` as items property set
3 | Provide the function to convert the user typed text value to a `QueryFilter`

##### Use select inputs with enumerations

The `Input` API and the `Components.input` API provides convenience methods to create enumeration based select inputs, automatically adding all the available enumeration values to the selection items set.

A `enum` type select can be created both as a `SingleSelect` and as `MultiSelect`.

For example, given the following `enum` class:

    enum MyEnum {

      FIRST, SECOND, THIRD;

    }

A select type input for the enumeration values can be created as follows:

    SingleSelect<MyEnum> singleSelect = Input.enumSelect(MyEnum.class).build(); (1)
    singleSelect = Input.enumOptionSelect(MyEnum.class).build(); (2)

    MultiSelect<MyEnum> multiSelect = Input.enumMultiSelect(MyEnum.class).build(); (3)

1 | Create a `SingleSelect` for the `MyEnum` enumeration
2 | Create a `SingleSelect` for the `MyEnum` enumeration using the options rendering mode
3 | Create a `MultiSelect` for the `MyEnum` enumeration

The Caption annotation can be used on the enumeration class values to configure the select items caption, with localizable messages support.

    enum MyEnum {

      @Caption(value = "The first", messageCode = "first.message.code")
      FIRST,

      @Caption(value = "The second", messageCode = "second.message.code")
      SECOND,

      @Caption(value = "The third", messageCode = "third.message.code")
      THIRD;

    }

See the next section to learn how to configure the select items caption using the select input builder API.

##### Selection items caption

By default, the selectable items are displayed in UI using the `toString()` representation of the item itself.

To change this behaviour, the item captions can be configured either setting them explicitly using the builder API (through the `itemCaption` method), or using a `ItemCaptionGenerator` function to provide the caption for each selection item.

Example using explicit item captions:

    SingleSelect<Integer> singleSelect = Input.singleSelect(Integer.class) (1)
        .items(1, 2) //
        .itemCaption(1, "One") (2)
        .itemCaption(2, "One", "two.message.code") (3)
        .build();

1 | Create a `Integer` type `SingleSelect`
2 | Set the `1` item caption
3 | Set the `2` item caption using a localizable message

Example using a `ItemCaptionGenerator`:

    SingleSelect<Long> singleSelect = Input.singleSelect(ID) (1)
        .dataSource(getDatastore(), TARGET, SUBJECT) (2)
        .itemCaptionGenerator(item -> item.getValue(NAME)) (3)
        .build();

1 | Create a `SingleSelect` using the `ID` selection property
2 | Use `SUBJECT` as items property set, which includes the `NAME` property
3 | Set the `ItemCaptionGenerator`: the `NAME` property value is used as item caption

For `Property` bound selectable inputs, a convenience `itemCaptionProperty` builder method is available to provide the property to use to obtain the item value which will be used as items caption.

    SingleSelect<Long> singleSelect = Input.singleSelect(ID) (1)
        .dataSource(getDatastore(), TARGET, SUBJECT) (2)
        .itemCaptionProperty(NAME) (3)
        .build();

1 | Create a `SingleSelect` using the `ID` selection property
2 | Use `SUBJECT` as items property set, which includes the `NAME` property
3 | The `NAME` property value is used as item caption

#### 3.9.5. Extend the Input API using adapters

The `Input` API can be extended using custom adapters, i.e. a class/interface to provide additional Input attributes and/or functionalities.

An adapter can be registered at `Input` build time using the `withAdapter` method, providing:

- The adapter `Class`

- A `Function` to provide the adapter instance when requested, with the `Input` instance as function argument.

An adapter instance can be obtained using the `Input` API method `<A> Optional<A> as(Class<A> type)`. If an adapter of the given `type` is available (i.e. was registered as described above), the adapter function will be invoked to provide the adapter instance.

    Input<String> input = Input.string().withAdapter(MyExtension.class, i -> new MyExtension()) (1)
        .build();

    Optional<MyExtension> extension = input.as(MyExtension.class); (2)

1 | Register and adapter for the `MyExtension` type
2 | Get the `MyExtension` type instance, if available

#### 3.9.6. Validatable inputs

The value of any `Input` component can be validated using the standard Holon Platform Validator API, through the ValidatableInput API.

An `Input` can be made validatable, adding support for `Validator` registration, using:

1. The `validatable` builder method:

    ValidatableInput<String> validatableInput = Input.string() //
        .validatable() (1)
        .withValidator(Validator.max(10)) (2)
        .validateOnValueChange(true) (3)
        .build();

1 | Make the input validatable
2 | Add a input value `Validator`
3 | Set whether to automatically validate the input value when it changes

2. The `ValidatableInput` adapter:

    Input<String> input = Input.string().build();

    ValidatableInput<String> validatableInput = ValidatableInput.builder(input) (1)
        .withValidator(Validator.max(10)) (2)
        .build();

    validatableInput = ValidatableInput.from(input); (3)
    validatableInput.addValidator(Validator.max(10)); (4)

1 | Use the `ValidatableInput` builder method to create and configure a validatable input from a standard `Input`
2 | Add a input value `Validator`
3 | Use the `ValidatableInput` from method to directly create a validatable input from a standard `Input`
4 | Add a input value `Validator` using the `addValidator` method

A `ValidatableInput` extends the Validatable API, which provides method to validate the input value using the registered validators.

    ValidatableInput<String> validatableInput = Input.string().validatable().build(); (1)

    validatableInput.isValid(); (2)

    try {
      validatableInput.validate(); (3)
    } catch (ValidationException e) {
      /* value is not valid */
    }

    Optional<String> value = validatableInput.getValueIfValid(); (4)

1 | Create a `ValidatableInput`
2 | Check whether the input value is valid
3 | Validate the input value, throwing a `ValidationException` if the validation fails
4 | Get the input value only if it is valid

By default, the validation errors are notified to the user using the UI component error message, if supported by the concrete input component.

The validation errors notification strategy can be customized using a `ValidationStatusHandler` function. The validation event provides the validation status (valid, invalid or unresolved) and the current validation errors, if any.

    ValidatableInput<String> validatableInput = Input.string().validatable() //
        .validationStatusHandler(event -> { (1)
          Status validationStatus = event.getStatus();
          String error = event.getErrorMessage();
          /* notify the validation errors */
        }).build();

1 | Set the `ValidationStatusHandler` to use for the `ValidatableInput`

| the Validatable API provides a set of `adapt` methods to use a Vaadin `com.vaadin.flow.data.binder.Validator` as a Holon Platform `Validator`.

#### 3.9.7. Organize `Input` components in groups and forms

A set of `Input` components can be grouped and organized using a PropertyInputGroup, using the Holon Platform Property model to bind each `Input` to a property definition.

The property definitions will be used as references to get and configure the `Input` instances managed by the group and to get and set the group values using a `PropertyBox` type.

The `PropertyInputGroup` API provides method to inspect the available properties and the `Input` instances bound to each property. Through the `ValueHolder` API, the group value can be setted and managed (see The `ValueHolder` interface).

When a `PropertyBox` type value is setted for the group, each `Input` value bound to a property is setted according to the property value provided by the `PropertyBox` instance, if available.

When a the group value is obtained using the `getValue()` method, the current `Input` values are reflected into the `PropertyBox` instance, using the property to which each `Input` is bound.

To create a `PropertyInputGroup`, the property set to use must be provided at build time. Both the `PropertyInputGroup` API and the `Components` API (through the `Components.input` sub interface) can be used to obtain a `PropertyInputGroup` builder.

By default, the property rendering architecture is used to automatically generate the `Input` components for each property of the group property set (see `Input` property renderer).

For example, given the following property model definition:

    static final NumericProperty<Long> ID = NumericProperty.longType("id");
    static final StringProperty NAME = StringProperty.create("name");
    static final PropertySet<?> SUBJECT = PropertySet.of(ID, NAME);

A `PropertyInputGroup` can be created in the following way:

    PropertyInputGroup group = PropertyInputGroup.builder(SUBJECT).build(); (1)
    group = Components.input.propertyGroup(SUBJECT).build(); (2)

    Collection<Property<?>> properties = group.getProperties(); (3)
    Stream<Input<?>> components = group.getElements(); (4)
    group.getBindings().forEach(binding -> { (5)
      Property<?> property = binding.getProperty();
      Input<?> component = binding.getElement();
    });

    Optional<Input<?>> element = group.getElement(NAME); (6)
    Input<?> component = group.requireElement(NAME); (7)

    PropertyBox value = PropertyBox.builder(SUBJECT).set(ID, 1L).set(NAME, "One").build();

    group.setValue(value); (8)
    value = group.getValue(); (9)

    group.clear(); (10)
    group.isEmpty(); (11)

1 | Create a `PropertyInputGroup` using the `SUBJECT` property set. The `Input` for each property will be automatically generated using the property renderers
2 | Create a `PropertyInputGroup` from the `Components` API
3 | Get the group property set
4 | Get the group `Input` elements
5 | Get the group bindings, i.e. the `Input` bound to each property
6 | Get the `Input` bound to the `NAME` property, if available
7 | Require the `Input` bound to the `NAME` property
8 | Set the group value using a `PropertyBox`: each property value available from the `PropertyBox` instance will be setted into the corresponding `Input`, if available
9 | Get the current group value: the current `Input` values (which in the meanwhile could have been changed by the user) are updated into the `PropertyBox` instance, according to the property to which each `Input` is bound
10 | Clear the group value
11 | Check whether the group is empty, i.e. has no value

To customize this behaviour and provide the `Input` component to use for one or more property, the `PropertyInputGroup` builder API provides a set of `bind` methods, which can be use to explicitly bind a `Input` instance to a property.

    PropertyInputGroup group = PropertyInputGroup.builder(SUBJECT) (1)
        .bind(NAME, Input.string().build()) (2)
        .bind(NAME, property -> Input.stringArea().build()) (3)
        .build();

1 | Create a `PropertyInputGroup` using the `SUBJECT` property set
2 | Bind a `Input` instance to the `NAME` property
3 | Bind a `Input` instance to the `NAME` property using a function

##### Input group configuration

The `PropertyInputGroup` builder API provides method to configure the group, allowing to:

- Hide one or more property: the hidden property won’t be bound to a `Input`

- Add a post processor to configure the `Input` instances just before the binding occurs

- Provide a default value for one or more `Input` components

- Add group value change listeners

    PropertyInputGroup group = PropertyInputGroup.builder(SUBJECT) (1)
        .hidden(ID) (2)
        .defaultValue(NAME, () -> "(no name)") (3)
        .withPostProcessor((property, component) -> { (4)
          /* Inputs configuration */
          component.hasStyle().ifPresent(s -> s.addClassName("my-style"));
        }) //
        .withValueChangeListener(event -> { (5)
          /* handle value change */
          PropertyBox value = event.getValue();
        }).build();

1 | Create a `PropertyInputGroup` using the `SUBJECT` property set
2 | Set the `ID` property as hidden
3 | Set the default value supplier for the `NAME` property
4 | Add a binding post processor
5 | Add a value change listener

##### Using a `PropertyInputForm` to make the group a UI component

The `PropertyInputForm` API handles a group of `Input` components bound to a property set, but it is not a UI component itself. The PropertyInputForm API can be used to provide a UI component for the group and use it as a form in application UI.

A `PropertyInputForm` extends the `HasComponent` interface to provide the actual group UI component (see The `HasComponent` interface) and the Composable API to declare the UI component to use as group elements container and the strategy to apply to organize the `Input` group elements into the group content area.

The `Composer` API can be used to implement the composition logic, i.e. to add the available `ViewComponent` elements to the UI component declared as group content. The `Composer` function provides:

- The group UI content element.

- A reference to the group API to obtain the `Input` elements (and the corresponding property bindings) to add to the group UI content element.

A default `Composer` for a `com.vaadin.flow.component.HasComponents` type UI element can be obtain using the `componentContainerComposer()` method of the `Composable` API. This composer adds the group elements sequentially to the `HasComponents` group content element, in the order they are provided from the group property set.

    PropertyInputForm form = PropertyInputForm.builder(new VerticalLayout(), SUBJECT) (1)
        .composer(Composable.componentContainerComposer()) (2)
        .build();

    myLayout.add(form.getComponent()); (3)

    form.setValue(PropertyBox.builder(SUBJECT).set(ID, 1L).set(NAME, "One").build()); (4)

1 | Create a `PropertyInputForm` using the `SUBJECT` property set, a `VerticalLayout` as group UI element
2 | The default component container composer is used
3 | The `getComponent()` method can be used to add the `PropertyInputForm` to a layout
4 | Set a form value

A set of convenience builder methods are available for the base Vaadin layouts:

    PropertyInputForm form = PropertyInputForm.verticalLayout(SUBJECT).build(); (1)
    form = PropertyInputForm.horizontalLayout(SUBJECT).build(); (2)
    form = PropertyInputForm.formLayout(SUBJECT).build(); (3)

    // Using the Components API:
    form = Components.input.formVertical(SUBJECT).build();
    form = Components.input.formHorizontal(SUBJECT).build();
    form = Components.input.form(SUBJECT).build();

1 | Create a `PropertyInputForm` using the `SUBJECT` property set and a `VerticalLayout` as group UI element
2 | Create a `PropertyInputForm` using the `SUBJECT` property set and a `HorizontalLayout` as group UI element
3 | Create a `PropertyInputForm` using the `SUBJECT` property set and a `FormLayout` as group UI element

A custom `Composer` can be used to control and customize the group element composition strategy:

    PropertyInputForm form = PropertyInputForm.verticalLayout(SUBJECT) //
        .composer((content, group) -> { (1)
          group.getBindings().forEach(binding -> {
            content.add(binding.getElement().getComponent());
          });
        }).build();

1 | Provide a custom composition logic

##### Form configuration

A `PropertyInputForm` can be configured using the builder API in order to:

- Hide one or more property: the hidden property won’t be bound to a `Input`

- Add an initializer to configure the form UI content

- Add a post processor to configure the `Input` instances just before the binding occurs

- Add form value change listeners

- Configure the property captions, i.e. to set the label to use for the `Input` bound to a property

    PropertyInputForm.formLayout(SUBJECT) (1)
        .hidden(ID) (2)
        .initializer(content -> { (3)
          /* content configuration */
          FormLayout fl = content;
        }).withPostProcessor((property, component) -> { (4)
          /* Inputs configuration */
          component.hasStyle().ifPresent(s -> s.addClassName("my-style"));
        }) //
        .withValueChangeListener(event -> { (5)
          /* handle value change */
          PropertyBox value = event.getValue();
        }) //
        .hidePropertyCaption(ID) (6)
        .propertyCaption(NAME, "My name", "name.message.code") (7)
        .build();

1 | Create a `PropertyInputForm` using the `SUBJECT` property set and a `FormLayout`
2 | Set the `ID` property as hidden
3 | Set the form content initializer
4 | Set the binding post processor
5 | Add a value change listener
6 | Hide the `ID` property caption
7 | Set the localizable caption for the `NAME` property

##### Input group and form validation

The `PropertyInputGroup` and the `PropertyInputForm` APIs provides `Input` validation support using the standard Holon Platform Validator API. The value validation is supported:

- At property level, to validate the single `Input` value for each property.

- At group level, to validate the overall `PropertyBox` type group value.

The validators can be added using the `PropertyInputGroup` and the `PropertyInputForm` builder APIs.

    PropertyInputForm.formLayout(SUBJECT) (1)
        .withValidator(NAME, Validator.max(10)) (2)
        .withValidator(propertyBox -> { (3)
          /* group value validation */
        }).validateOnValueChange(true) (4)
        .build();

1 | Create a `PropertyInputForm` using the `SUBJECT` property set
2 | Add a validator for the `Input` component bound to the `NAME` property
3 | Add a group value validator
4 | Set whether to validate the `Input` values when each `Input` value changes

The `PropertyInputGroup` and the `PropertyInputForm` APIs provides a set of methods to perform the group/form validation, a part of which is inherited from the Validatable API.

    PropertyInputForm form = PropertyInputForm.formLayout(SUBJECT).build();

    form.isValid(); (1)
    try {
      form.validate(); (2)
    } catch (ValidationException e) {
      /* value is not valid */
    }

    Optional<PropertyBox> valueIfValid = form.getValueIfValid(); (3)
    PropertyBox value = form.getValue(); (4)
    value = form.getValue(false); (5)

1 | Check whether the form is valid
2 | Validate the form, firing both property level and group level validators
3 | Get the form value, returning an empty `Optional` if validation fails
4 | By default, when the form value is requested, the form validation is performed
5 | Get the form value skipping validation

##### Input groups validation status handler

By default, for the `PropertyInputGroup` and the `PropertyInputForm` components, the validation errors originated by the registered validators are notified to the user in the following way:

- For property level validators, if the `Input` component supports error messages notification (using the Vaadin `HasValidation` interface), the validation errors are setted as component errors.

- For group level validators, a `Dialog` is used to notify the validation errors.

The validation status errors notification can be customized using the ValidationStatusHandler interface, both at property and group level.

The `ValidationStatusHandler` validation event provides the validation status (valid, invalid or unresolved) and the current validation errors, if any.

To customize both the property level and the group level validation status notification, the `validationStatusHandler` builder method can be used.

    PropertyInputForm form = PropertyInputForm.formLayout(SUBJECT) //
        .validationStatusHandler(event -> { (1)
          if (event.isInvalid()) {
            Notification.show("Validation falied: " + event.getErrorMessage());
          }
        }).validationStatusHandler(NAME, event -> { (2)
          /* omitted */
        }).build();

1 | Set a custom group level validation status handler
2 | Set a custom property level validation status handler for the `NAME` property

Furthermore, the GroupValidationStatusHandler interface can be used to override all the validation status notification, customizing both the property level and the group level validation status notification using a single handler.

    PropertyInputForm form = PropertyInputForm.formLayout(SUBJECT) //
        .groupValidationStatusHandler(event -> { (1)
          event.getGroupStatus(); (2)
          event.getInputsValidationStatus(); (3)
          event.getGroupErrorMessages(); (4)
          event.getInputsValidationStatus().forEach(s -> s.getErrorMessages()); (5)
        }).build();

1 | Set the `GroupValidationStatusHandler` for the form
2 | Get the group level validation status
3 | Get the single `Input` validation status
4 | Get the group level validation errors
5 | Get the single `Input` validation errors

## 4. Vaadin session scope

When the `holon-vaadin-flow` artifact is in classpath, a Holon Platform Context scope bound to the current Vaadin session is automatically registered and available to manage context resources.

The VaadinSessionScope API can be used to obtain the scope name. The `VaadinSessionScope` API also provides convenience methods to access the Vaadin session scope.

The Vaadin session attributes are used as context resource registry and the a current `VaadinSession` must be available in order for the scope to work.

    Optional<ContextScope> scope = Context.get().scope(VaadinSessionScope.NAME); (1)
    scope = VaadinSessionScope.get(); (2)
    ContextScope sessionScope = VaadinSessionScope.require(); (3)

1 | Get the session scope using the scope name
2 | Get the session scope using the `VaadinSessionScope` API
3 | Require the session scope using the `VaadinSessionScope` API

For example, if a `LocalizationContext` is bound to the current Vaadin session using a session attribute, it can be retrieved using the standard Holon Platform `Context` API.

    VaadinSession.getCurrent().setAttribute(LocalizationContext.class, (1)
        LocalizationContext.builder().withInitialLocale(Locale.US).build());

    Optional<LocalizationContext> localizationContext = Context.get().resource(LocalizationContext.class); (2)

    localizationContext = LocalizationContext.getCurrent(); (3)

1 | Bind a `LocalizationContext` instance to the current Vaadin session attribute
2 | The `LocalizationContext` instance is now available as a context resource
3 | The `getCurrent()` method will return the `LocalizationContext` instance

## 5. Device information

| Since version 5.2.7, the DeviceInfo API is deprecated: use `com.vaadin.flow.server.WebBrowser` instead (it can be obtained from `VaadinSession`).

## 6. Routing and navigation

Maven coordinates:

    <groupId>com.holon-platform.vaadin</groupId>
    <artifactId>holon-vaadin-flow-navigator</artifactId>
    <version>5.2.13</version>

The `holon-vaadin-flow-navigator` artifact provides URL query parameters marshalling and unmarshalling between URL representation and Java types using the `@QueryParameter` annotation and a `Navigator` API which can be used to handle the application UI views routing

Furthermore, a complete support for view authentication and authorization is provided, using the Holon Platform core authentication APIs.

### 6.1. Navigation parameters handling

When the `holon-vaadin-flow-navigator` artifact is in classpath, the URL query parameters marshalling and unmarshalling for application routes is automatically enabled and setted up at application bootstrap.

The URL query parameters value handling can thus be implemented using the QueryParameter annotation on routing target classes (i.e. UI component classes annotated with `@Route`) class fields.

| For information about the Vaadin Flow routing architecture, including the `@Route` annotation and route layouts, see the Vaadin Flow documentation.

When a routing target class field is annotated with `@QueryParameter`, its value will be automatically setted using the corresponding URL query parameter value, if available, just before the component is rendered in application UI.

The `String` type URL query parameter value will be converted to the required Java type declared by the field type. See Built in query parameter types for the Java types supported by default and Adding query parameter type support to extend the supported Java types.

By default, the URL query parameter name bound to a `@QueryParameter` field is equal to the field name.

    @Route("some/path")
    public class View extends Div {

      @QueryParameter (1)
      private Integer parameter;

    }

1 | The bound URL query parameter name is the field name, i.e. `parameter`. For example, when the route `some/path?parameter=1` is used, the `parameter` field value will be setted to the `1` Integer value.

The `value()` annotation attribute can be used to declare the URL query parameter name to which the field is bound, if you don’t want to use the field name.

    @Route("some/path")
    public class View extends Div {

      @QueryParameter("myparam") (1)
      private Integer parameter;

    }

1 | The URL query parameter name bound to the `parameter` field is `myparam`. For example, when the route `some/path?myparam=1` is used, the `parameter` field value will be setted to the `1` Integer value.

The routing target class field declaration (even `private`) it’s enough to enable the the query parameter value handling, but the standard Java Beans convention can be also used, providing a setter method to set the field value.

If a field setter method is available in the routing target class, it will be used to set the query parameter field value. This allows, for example, to perform some operations one the query parameter value before it is setted as field value.

    @Route("some/path")
    public class View extends Div {

      @QueryParameter
      private Integer parameter;

      public void setParameter(Integer parameter) { (1)
        this.parameter = parameter;
      }

    }

1 | The setter method will be used to set the `parameter` query parameter field value

#### 6.1.1. Query parameter URL encoding and decoding

By default, all the navigation related APIs automatically handle the query parameter names and values encoding, when serialized to a URL, and decoding, when deserialized from a URL.

The query parameter names and values encoding and decoding is performed using the `application/x-www-form-urlencoded` MIME type and the default `UTF-8` charset.

Each API which handles URL query parameters provides method to skip the query parameter names and values encoding and decoding, if required.

See the specific API documentation below for further details.

#### 6.1.2. Using the injected parameter values

The URL query paramter values are automatically injected in the routing target class `@QueryParameter` annotated fields at the *after navigation* routing lifecycle event, i.e. when the routing target component instance is added to the UI.

For this reason, consistent parameter values are only available from this phase on. To handle and use the `@QueryParameter` annotated fields value, you have to ensure to be at least in the after navigation lifecycle phase of the routing component.

For this purpose, the `com.vaadin.flow.router.AfterNavigationObserver` interface can be used, implementing it by the routing target class.

    @Route("some/path")
    public class View extends Div implements AfterNavigationObserver { (1)

      @QueryParameter
      private Integer parameter;

      @Override
      public void afterNavigation(AfterNavigationEvent event) { (2)
        /* handle the parameters value */
        Notification.show("Parameter value: " + this.parameter);
      }

    }

1 | Implement the `AfterNavigationObserver` interface to manage after navigation events
2 | When the after navigation event occurs, all the `@QueryParameter` fields values are consistent and already injected using the URL query parameters

Since it is bound to the same after navigation lifecycle phase, a `@OnShow` annotated method can also be used.

    @Route("some/path")
    public class View extends Div {

      @QueryParameter
      private Integer parameter;

      @OnShow (1)
      public void processParameters() {
        /* handle the parameters value */
        Notification.show("Parameter value: " + this.parameter);
      }

    }

1 | When a `@OnShow` annotated method in invoked, all the `@QueryParameter` fields values are consistent and already injected using the URL query parameters

See Using `@OnShow` on route target classes for details.

#### 6.1.3. Direct query parameter values deserialization

The NavigationParameters API can be used to directly deserialize URL query parameter values into the supported Java types.

The `NavigationParameters` API provides a set of builder methods to create a `NavigationParameters` handler instance from a `Map` of query parameter name and values, from a `com.vaadin.flow.router.QueryParameters` instance or from a `com.vaadin.flow.router.Location` reference.

    Map<String, List<String>> queryParameters = getQueryParameters();
    NavigationParameters navigationParameters = NavigationParameters.create(queryParameters); (1)

    navigationParameters = NavigationParameters
        .create(QueryParameters.simple(Collections.singletonMap("test", "value"))); (2)

    navigationParameters = NavigationParameters.create(new Location("host.com/?test=value")); (3)

1 | Create a `NavigationParameters` from a `Map` of query parameter name and values
2 | Create a `NavigationParameters` from a `com.vaadin.flow.router.QueryParameters` instance
3 | Create a `NavigationParameters` from a `com.vaadin.flow.router.Location` reference

By default, the query parameter names and values are decoded from the URL representation, using the `application/x-www-form-urlencoded` MIME type and the default `UTF-8` charset.

To skip query parameter names and values decoding, the `NavigationParameters` API builder methods provides a `decode` parameter which can be set to `false`.

    NavigationParameters navigationParameters = NavigationParameters.create(getQueryParameters(), false); (1)

1 | Set the `decode` parameter to `false` to skip the query parameter names and values decoding

The `NavigationParameters` API provides a set of methods to obtain the query parameter values, deserialized to the required Java type, if supported.

| See Built in query parameter types for the Java types supported by default and Adding query parameter type support to extend the supported Java types.

    NavigationParameters navigationParameters = NavigationParameters.create(getQueryParameters()); (1)

    boolean hasParameterAndValue = navigationParameters.hasQueryParameter("myparam"); (2)

    List<Integer> values = navigationParameters.getQueryParameterValues("myparam", Integer.class); (3)

    Optional<Integer> value = navigationParameters.getQueryParameterValue("myparam", Integer.class); (4)

    Integer valueOrDefault = navigationParameters.getQueryParameterValue("myparam", Integer.class, 0); (5)

1 | Create a `NavigationParameters` handler
2 | Check if a parameter named `myparam` is present and has a value
3 | Get the values of the parameter named `myparam`, deserialized using the `Integer` type
4 | Get the single value of the parameter named `myparam`, deserialized using the `Integer` type, if available
5 | Get the single value of the parameter named `myparam`, deserialized using the `Integer` type, or the default `0` value

#### 6.1.4. Built in query parameter types

By default, the following Java types are supported for query parameter values conversion from the URL query string:

Type | Sub type | Format
--- | --- | ---
String | [NONE] | Any text
Number | `Integer`, `Long`, `Short`, `Byte`, `Float`, `Double`, `BigInteger`, `BigDecimal` | For decimal numbers, the dot (`.`) character must be used as decimal positions separator. The `-` character can be used for negative numbers. Hexadecimal representation is supported using the `0x` or `0X` prefix.
Boolean | [NONE] | `true` or `false`
Enums | [NONE] | The enumeration value name
LocalDate | [NONE] | ISO date format, for example `2019-01-11`
LocalTime | [NONE] | ISO time format, for example `10:15` or `10:15:30`
LocalDateTime | [NONE] | ISO date and time format, for example `2019-01-11T10:15:30`
OffsetTime | [NONE] | ISO time format with offset support, for example `10:15:30+01:00`
OffsetDateTime | [NONE] | ISO date and time format with offset support, for example `2019-01-11T10:15:30+01:00` or `2019-01-11T10:15:30+01:00[Europe/Paris]`
java.util.Date | [NONE] | ISO date and/or time format, for example `2019-01-11` or `2019-01-11T10:15:30`

#### 6.1.5. Optional query parameter values

The `java.util.Optional` class is supported for `@QueryParameter` field type declarations.

Using `Optional`, the field value will never be `null`, and when the parameter value is not available a `Optional.empty()` value is setted as field value.

    @Route("some/path")
    public class View extends Div {

      @QueryParameter
      private Optional<String> parameter; (1)

    }

1 | `Optional` query parameter `String` type declaration

#### 6.1.6. Multiple query parameter values

Multiple query parameter values are supported either using the `java.util.Set` or `java.util.List` class.

For example, given the following routing target class:

    @Route("some/path")
    public class View extends Div {

      @QueryParameter
      private Set<String> parameter; (1)

    }

1 | Query parameter with multiple value support declaration using a `java.util.Set`

For the routing URL `some/path?parameter=a&parameter=b`, the `parameter` field value will be a `java.util.Set` instance containing the `a` and `b` String values.

When the URL query parameter value is not available, a empty `java.util.Set` or `java.util.List` is setted as field value.

#### 6.1.7. Adding query parameter type support

The `@QueryParameter` annotated fields supported Java types set can be extended, adding support for new Java types marshalling and unmarshalling, using the NavigationParameterTypeMapper API.

To add support for a new query parameter type, a `NavigationParameterTypeMapper` instance bound to the required type can be created and automatically registered using the Java service extension architecture, i.e. providing a `com.holonplatform.vaadin.flow.navigator.NavigationParameterTypeMapper` named file in the `META-INF/services` folder of a jar, containing the `NavigationParameterTypeMapper` concrete class names to register.

For example, suppose we need to handle the following `MyType` parameter type:

    public class MyType {

      private final int value;

      public MyType(int value) {
        this.value = value;
      }

      public int getValue() {
        return value;
      }

    }

We can create a new `NavigationParameterTypeMapper` class, generalized on the `MyType` type, as follows:

    public class MyTypeParameterMapper implements NavigationParameterTypeMapper<MyType> {

      @Override
      public Class<MyType> getParameterType() { (1)
        return MyType.class;
      }

      @Override
      public String serialize(MyType value) throws InvalidNavigationParameterException { (2)
        if (value != null) {
          return String.valueOf(value.getValue());
        }
        return null;
      }

      @Override
      public MyType deserialize(String value) throws InvalidNavigationParameterException { (3)
        if (value != null) {
          return new MyType(Integer.valueOf(value));
        }
        return null;
      }

    }

1 | Handled parameter type declaration
2 | Parameter value unmarshalling to the `String` type URL query parameter value
3 | Parameter value marshalling from the `String` type URL query parameter value

An then register the `MyTypeParameterMapper` class using the Java service extension architecture, creating a suitable file under the `META-INF/services` folder:

com.holonplatform.vaadin.flow.navigator.NavigationParameterTypeMapper file

    my.package.MyTypeParameterMapper

This way, the `MyType` parameter type will be automatically handled using the `@QueryParameter` annotation.

    @Route("some/path")
    public class View extends Div {

      @QueryParameter
      private MyType parameter; (1)

    }

1 | The `MyType` type parameter is handled using the `MyTypeParameterMapper` class

#### 6.1.8. Required query parameters

The `required()` attribute of the `@QueryParameter` annotation can be used to declare required query parameter values.

When a required query parameter value is not available from the URL query string, a navigation error is fired before the navigation to the routing target occurs.

The InvalidNavigationParameterException is used to notify the error and interrupt the navigation.

    @Route("some/path")
    public class View extends Div {

      @QueryParameter(required = true) (1)
      private Integer parameter;

    }

1 | The query parameter is required

See Default query parameter values to provide a default value for a parameter, which can be used to provide a default value for a required parameter when it is not available from the URL query string.

#### 6.1.9. Default query parameter values

The `defaultValue()` attribute of the `@QueryParameter` annotation can be used to declare a default value for a query parameter. This value will be used and injected into the parameter field when the parameter value is not available from the URL query string.

The `defaultValue()` attribute value is a `String`, and the format conventions described in Built in query parameter types should be used as `String` format for the supported Java types.

    @Route("some/path")
    public class View extends Div {

      @QueryParameter(defaultValue = "0") (1)
      private Integer parameter;

    }

1 | Declare the parameter default value

### 6.2. Using `@OnShow` on route target classes

The OnShow annotation can be used un route target class methods to handle the *after navigation* routing lifecycle event, i.e. to execute code when the routing target component instance is added to the UI.

A method annotation with `@OnShow`:

- Must be `public`.

- Can declare either no parameters or a single parameter of type `com.vaadin.flow.router.AfterNavigationEvent`, to obtain the event which triggered the method invocation.

Any valid `@OnShow` annotated method (including super classes) in invoked at the after navigation phase of the routing target component. No invocation order is guaranteed.

    @Route("some/path")
    public class View extends Div {

      @OnShow (1)
      public void afterNavigation1() {
        /* ... */
      }

      @OnShow (2)
      public void afterNavigation2(AfterNavigationEvent event) {
        /* ... */
      }

    }

1 | Declare the method to be invoked just after the navigation to this routing target
2 | Declare the method to be invoked just after the navigation to this routing target, providing the `AfterNavigationEvent` type event

### 6.3. The `Navigator` API

The Navigator API can be used to handle the application routing, i.e. the navigation between the UI components which represent the application views.

Each `Navigator` is bound to a UI and the `Navigator` API for the current UI can be obtained using the `get()` static method. This method checks if a `Navigator` instance is available as a context resource and if not uses an internal registry to obtain the instance bound to the current UI, creating a new instance if none was bound to the UI yet.

| See the Holon Platform Context documentation for information about the context resources management.

    Navigator navigator = Navigator.get(); (1)

1 | Get the `Navigator` API for the current UI

A `Navigator` instance can also be directly created for a specific UI using the `create` static method.

    Navigator navigator = Navigator.create(myUI); (1)

1 | Create a `Navigator` for the given UI

The `Navigator` API makes available a set of methods to handle the routing between the application’s declared route targets, ensuring a consistent query parameters management with Java types marshalling support (see Navigation parameters handling) and providing suitable routing URL builders using the supported Java types to provide the query parameters value.

See Built in query parameter types to learn about the default supported Java types for query parameters declaration and Adding query parameter type support to learn how to add support for additional Java types.

| For information about the Vaadin Flow routing architecture, including the `@Route` annotation and route layouts, see the Vaadin Flow documentation.

The `Navigator` API provides a set of `navigateTo(…​)` methods to perform navigation towards a routing target. The routing target URL can be declared either using:

- The route path, as declared using the `@Route` annotation.

- The routing target class reference.

- A full URL location, which includes the route path and the optional query part with the query parameters declaration.

Each `Navigator` API `navigateTo(…​)` method provides multiple versions in order to:

- Specify the query parameter values, using a map of query parameter name and the corresponding value, provided as one of the supported Java type object. The `Navigator` API will take care of parameter value serialization to be used in the URL query part.

- Specify one or more path parameter, if the routing target class support them through the `com.vaadin.flow.router.HasUrlParameter` interface.

For example, supposing the following routing target class is registered in the application:

    @Route("some/path")
    public class View extends Div {

      @QueryParameter("myparam")
      private Integer parameter; (1)

    }

1 | Declares a single `Integer` type query parameter named `myparam`

The `Navigator` API can be used as follows to navigate to the routing target:

    Navigator navigator = Navigator.get(); (1)

    navigator.navigateTo("some/path"); (2)
    navigator.navigateTo("some/path", Collections.singletonMap("myparam", new Integer(1))); (3)

    navigator.navigateTo(View.class); (4)
    navigator.navigateTo(View.class, Collections.singletonMap("myparam", new Integer(1))); (5)

    navigator.navigateToLocation("some/path?myparam=1"); (6)

1 | Get the `Navigator` for the current UI
2 | Navigate to the `View` component using the route path
3 | Navigate to the `View` component using the route path and specifying the `myparam` query parameter value
4 | Navigate to the `View` component using the component class
5 | Navigate to the `View` component using the component class and specifying the `myparam` query parameter value
6 | Navigate to the `View` component using the full location URL, including the route path and the query parameters

Supposing the `View` component declares a path parameter using the `com.vaadin.flow.router.HasUrlParameter` interface:

    @Route("some/path")
    public class View extends Div implements HasUrlParameter<String> {

      @QueryParameter("myparam")
      private Integer parameter;

      @Override
      public void setParameter(BeforeEvent event, String parameter) {
        /* handle the path parameter value */
      }

    }

The `Navigator` API can be used as follows:

    Navigator navigator = Navigator.get(); (1)

    navigator.navigateTo(View.class, "value"); (2)
    navigator.navigateTo(View.class, "value", Collections.singletonMap("myparam", new Integer(1))); (3)

1 | Get the `Navigator` for the current UI
2 | Navigate to the `View` component using the component class and providing the path parameter `value`
3 | Navigate to the `View` component using the component class and providing both the path parameter `value` and the `myparam` query parameter value

Furthermore, the `Navigator` API provides provides two convenience methods:

- `navigateToDefault()`: to navigate to the default route, i.e. the empty (`""`) route, if available.

- `navigateBack()`: to navigate back in the browser navigation history.

    navigator.navigateToDefault(); (1)
    navigator.navigateBack(); (2)

1 | Navigate to the default route
2 | Navigate back in the browser navigation history

#### 6.3.1. The navigation builder API

The `Navigator` API provides a navigation URL builder API, available through the `navigation(…​)` methods, which allows to declare a routing target URL and its parameters (both query and path parameter types) using a fluent style builder and then either perform the actual navigation or obtain the complete location URL.

The navigation builder API can be obtained either specifying the route path or the routing target class and provides methods to set the path or query parameters to use.

The query parameter values are provided using one of the supported Java types, the `Navigator` API will take care of parameter value serialization to be used in the URL query part.

The navigation is performed using the `navigate()` method.

To obtain the complete URL location and do not perform the actual navigation, the `asLocation()` or `asLocationURL()` methods can be used, which provide the navigation URL as a `com.vaadin.flow.router.Location` object or a `String` respectively.

    Navigator navigator = Navigator.get(); (1)

    navigator.navigation("some/path") (2)
        .withQueryParameter("myparam", new Integer(1)) (3)
        .withQueryParameter("multi", "a", "b", "c") (4)
        .navigate(); (5)

    navigator.navigation(View.class) (6)
        .withPathParameter("value") (7)
        .navigate(); (8)

    Location location = navigator.navigation("some/path") //
        .withQueryParameter("myparam", new Integer(1)) //
        .asLocation(); (9)

    String url = navigator.navigation(View.class) //
        .withQueryParameter("myparam", new Integer(1)) //
        .asLocationURL(); (10)

1 | Get the `Navigator` for the current UI
2 | Build a navigation using a route path
3 | Add a query parameter value
4 | Add multiple query parameter values
5 | Perform the navigation action
6 | Build a navigation using a route target class
7 | Set the path parameter value
8 | Perform the navigation action
9 | Get the complete navigation URL as a `com.vaadin.flow.router.Location` object
10 | Get the complete navigation URL as a `String`

By default, the query parameter names and values are encoded to the URL representation, using the `application/x-www-form-urlencoded` MIME type and the default `UTF-8` charset.

To skip the query parameter names and values encoding, the `encodeQueryParameters` builder method can be used:

    Navigator.get().navigation("some/path") (1)
        .withQueryParameter("myparam", new Integer(1)) (2)
        .withQueryParameter("multi", "a", "b", "c") (3)
        .encodeQueryParameters(false) (4)
        .navigate(); (5)

1 | Build a navigation using a route path
2 | Add a query parameter value
3 | Add multiple query parameter values
4 | Disable the query parameters URL encoding
5 | Perform the navigation action

#### 6.3.2. Get the URL of a navigation target

The `Navigator` API provides a set of `getUrl(…​)` convenince methods to obtain the registered URL for a navigation target class.

    String url = navigator.getUrl(View.class); (1)
    url = navigator.getUrl(View.class, "path_param_value"); (2)
    url = navigator.getUrl(View.class, "path_param_value1", "path_param_value2"); (3)

1 | Get the `View` routing target class base URL
2 | Get the `View` routing target class URL with the provided path parameter value
3 | Get the `View` routing target class URL with the provided path parameter values

#### 6.3.3. Listening to navigation changes

The NavigationChangeListener listener interface can be use to listen to navigation target changes.

The navigation change event provides:

- The changed URL location.

- The changed navigation target component instance.

A `NavigationChangeListener` can be registered using the `Navigator` API `addNavigationChangeListener` method and it is invoked when a routing action is performed, i.e. when the current navigation target changes.

    Navigator navigator = Navigator.get(); (1)

    navigator.addNavigationChangeListener(event -> { (2)
      Location location = event.getLocation(); (3)
      HasElement target = event.getNavigationTarget(); (4)
    });

1 | Get the `Navigator` for the current UI
2 | Register a `NavigationChangeListener`
3 | The new navigation location
4 | The new navigation target instance

#### 6.3.4. Navigation links

The NavigationLink API represents a navigation link component, which handles navigation internally instead of loading a new page in the browser.

The `NavigationLink` API provides a builder API to configure the navigation target URL, either specifying a route path or a routing target class, and providing any path or query parameter value.

The query parameter values are provided using one of the supported Java types, the link implementation will take care of parameter value serialization to be used in the URL query part.

The `NavigationLink` API extends `HasComponent`, allowing to use it as a UI component through the `getComponent()` method. See The `HasComponent` interface.

    NavigationLink link = NavigationLink.builder("some/path") (1)
        .withQueryParameter("myparam", 123) (2)
        .text("Link text") (3)
        .build();

    link = NavigationLink.builder(View.class) (4)
        .withQueryParameter("myparam", 123) (5)
        .withPathParameter("value") (6)
        .text("Link text") (7)
        .build();

    myLayout.add(link.getComponent()); (8)

1 | Build a `NavigationLink` using a route path
2 | Add a query parameter value
3 | Set the link text
4 | Build a `NavigationLink` using a routing target class
5 | Add a query parameter value
6 | Add a path parameter value
7 | Set the link text
8 | Add the link component to a layout

By default, the query parameter names and values are encoded to the URL representation, using the `application/x-www-form-urlencoded` MIME type and the default `UTF-8` charset.

To skip the query parameter names and values encoding, the `encodeQueryParameters` builder method can be used:

    NavigationLink link = NavigationLink.builder("some/path") (1)
        .withQueryParameter("myparam", 123) (2)
        .encodeQueryParameters(false) (3)
        .text("Link text") (4)
        .build();

1 | Build a `NavigationLink` using a route path
2 | Add a query parameter value
3 | Disable the query parameters URL encoding
4 | Set the link text

### 6.4. Authentication support for UI routes

When the `holon-vaadin-flow-navigator` artifact is in classpath, the Authenticate annotation can be used on routing target classes to provide authentication support to the routing infrastructure.

A routing target class annotated with `@Authenticate` is under authentication control: only authenticated users can access the corresponding route.

An AuthContext definition is required in order to enable the authentication support and the `AuthContext` to use must be available as a context resource, for example bound to the Vaddin session.

| See the Holon Platform AuthContext documentation for information about the authentication context and the Realm documentation for information about the authentication configuration.

The `redirectURI()` attribute of the `@Authenticate` annotation can be used to specify a redirection URL to use when a not authenticated request is performed against an authentication protected route.

When a redirect URI is not provided and the authentication is not available for an authentication protected route, a UnauthorizedNavigationException is used to notify the error and interrupt the navigation.

    @Authenticate (1)
    @Route("some/path")
    public class View1 extends Div {

      /* content omitted */

    }

    @Authenticate(redirectURI = "login") (2)
    @Route("some/path")
    public class View2 extends Div {

      /* content omitted */

    }

1 | The `View1` routing target class, and so the `some/path` route path, can be accessed only by an authenticated user
2 | The `View2` routing target class, and so the `some/path` route path, can be accessed only by an authenticated user and a `login` redirect URI is specified and will be used to redirect the user navigation when the authentication is not available

The `@Authenticate` annotation can be also used on a routing layout class: any routing target class child of the layout will inherit the `@Authenticate` annotation definition.

    @Authenticate (1)
    public class MainLayout extends Div implements RouterLayout {

    }

    @Route(value = "some/path", layout = MainLayout.class) (2)
    public class View extends Div {

      /* content omitted */

    }

1 | The `@Authenticate` is declared on a `RouterLayout`: any child routing target class will inherit the authentication control declaration
2 | The `View` routing target class declares `MainLayout` as parent layout, so it will be under authentication control

### 6.5. Authorization support for UI routes

When the `holon-vaadin-flow-navigator` artifact is in classpath, the `javax.annotation.security.RolesAllowed` and `javax.annotation.security.PermitAll` annotations can be used on routing target classes to perform a role based authorization access control on routing targets.

An AuthContext definition is required in order to enable the authorization support and the `AuthContext` to use must be available as a context resource, for example bound to the Vaddin session.

| See the Holon Platform AuthContext documentation for information about the authentication context and the Realm documentation for information about the authentication configuration.

The user roles check is performed using the current `Authentication` permissions, provided by the `AuthContext`.

| See the Holon Platform Authorization documentation for information about the permissions configuration and control.

When the `javax.annotation.security.RolesAllowed` annotation is used, any of the specified role name must be granted to the current authenticated user in order to allow the route access.

When the authorization control fails, a ForbiddenNavigationException is used to notify the error and interrupt the navigation.

    @RolesAllowed({ "ROLE1", "ROLE2" }) (1)
    @Route("some/path")
    public class View extends Div {

      /* content omitted */

    }

1 | The `View` routing target class, and so the `some/path` route path, is under authorization control and can be accessed only if either the `ROLE1` or `ROLE2` role name is granted to the authenticated user

## 7. Spring integration

The `holon-vaadin-flow-spring` artifact provides support and integration with the Spring framework.

Maven coordinates:

    <groupId>com.holon-platform.vaadin</groupId>
    <artifactId>holon-vaadin-flow-spring</artifactId>
    <version>5.2.13</version>

The `holon-vaadin-flow-spring` artifact includes the standard Vaadin Flow Spring integration support, declaring the `vaadin-spring` artifact as dependency. See the Vaadin Spring documentation for information about the standard integration features and setup.

### 7.1. Provide the `Navigator` API as a Spring bean

The EnableNavigator annotation can be used on a Spring configuration class to made available a UI-scoped `Navigator` instance as a Spring bean.

The Vaadin Spring UI scope must be enabled to use this configuration annotation, for example using the `com.vaadin.flow.spring.annotation.EnableVaadin` annotation or the Vaadin Spring Boot integration auto-configuration facilities.

    @Configuration
    @EnableVaadin
    @EnableNavigator (1)
    class Config {

    }

    @Autowired
    Navigator navigator; (2)

1 | Enable the `Navigator` API UI-scoped Spring bean configuration
2 | Obtain the `Navigator` API instance for current UI using injection

### 7.2. Using Spring Security for authorization control

The EnableSecuredRoute annotation can be used on a Spring configuration class to enable the Spring Security `org.springframework.security.access.annotation.Secured` annotation on routing target classes to perform a role based route authorization access control.

| The Spring Security dependency must be explicitly provided by the project and must be available on classpath.

In order to use the `@Secured` annotation based authorization control, a `SecurityContext` must be available and properly configured.

When the `javax.annotation.security.RolesAllowed` annotation is used, any of the specified role name must be granted to the current authenticated user in order to allow the route access.

When the authorization control fails, a ForbiddenNavigationException is used to notify the error and interrupt the navigation.

## 8. Spring Boot integration

The `holon-vaadin-flow-spring-boot` artifact provides integration with Spring Boot, dealing with `Navigator` API and `LocalizationContext` integration auto configuration.

To enable the Spring Boot auto-configuration the following artifact must be included in your project dependencies:

Maven coordinates:

    <groupId>com.holon-platform.vaadin</groupId>
    <artifactId>holon-vaadin-flow-spring-boot</artifactId>
    <version>5.2.13</version>

The `holon-vaadin-flow-spring-boot` artifact includes the standard Vaadin Flow Spring Boot integration, declaring the `vaadin-spring` artifact as dependency. See the Vaadin Spring documentation for information about the standard integration features and setup.

### 8.1. `Navigator` API auto-configuration

The `Navigator` API auto configuration provides automatic setup of a UI-scoped `Navigator` bean, if a `Navigator` type bean is not already available in application context. See Provide the `Navigator` API as a Spring bean.

Furthermore, two default navigation error notification UI components are registered:

- One for the `UnauthorizedNavigationException`: see UnauthorizedNavigationError.

- One for the `ForbiddenNavigationException`: see ForbiddenNavigationError.

The `holon.vaadin.navigator.errors.enabled` application configuration property can be setted to `false` to disable the error components registration.

### 8.2. `LocalizationContext` integration auto configuration

The `LocalizationContext` integration auto-configuration provides the following features:

1. Localization context localization synchronization:

If a `LocalizationContext` type bean is available in context, and its scope is either UI (`vaadin-ui`) or Session (`session`) or Vaadin session (`vaadin-session`), when the `LocalizationContext` localization changes, the changed `Locale` is reflected to the current Vaadin UI or Vaadin session, according to bean scope.

This feature can be disabled setting the application configuration property `holon.vaadin.localization-context.reflect-locale` to `false`.

2. Localization context initialization:

If a `LocalizationContext` type bean is available in context, and its scope is either UI (`vaadin-ui`) or Session (`session`) or Vaadin session (`vaadin-session`), the initial `Locale` detected at session/UI initialization (according to bean scope) is setted to the `LocalizationContext` instance.

This feature can be disabled setting the application configuration property `holon.vaadin.localization-context.auto-init` to `false`.

3. Localization context `I18NProvider` integration:

If a `LocalizationContext` type bean is available in context, and a `I18NProvider` type bean is not available, the detected `LocalizationContext` is used as `I18NProvider` and registered as a Spring bean using the `LocalizationContextI18NProvider` API.

See Use a LocalizationContext as I18NProvider.

This feature can be disabled setting the application configuration property `holon.vaadin.localization-context.i18nprovider` to `false`.

### 8.3. Spring Boot starters

The following starter artifacts are available to provide a quick project configuration setup using Maven dependency system:

1. The Vaadin Flow starter provides the dependencies to the Vaadin Flow Spring Boot integration artifact `holon-vaadin-flow-spring-boot`, in addition to:

- The Holon Platform Core Module Spring Boot integration base starter (`holon-starter`).

- The Spring Boot `spring-boot-starter-web` starter, which includes the embedded Tomcat auto-configuration.

See the Spring Boot starters documentation for details on Spring Boot starters.

Maven coordinates:

    <groupId>com.holon-platform.vaadin</groupId>
    <artifactId>holon-starter-vaadin-flow</artifactId>
    <version>5.2.13</version>

2. The Vaadin Flow starter using Undertow provides the same dependencies as the previous starter, but uses Undertow instead of Tomcat as embedded servlet container.

Maven coordinates:

    <groupId>com.holon-platform.vaadin</groupId>
    <artifactId>holon-starter-vaadin-flow-undertow</artifactId>
    <version>5.2.13</version>

## 9. Loggers

By default, the Holon platform uses the SLF4J API for logging. The use of SLF4J is optional: it is enabled when the presence of SLF4J is detected in the classpath. Otherwise, logging will fall back to JUL (`java.util.logging`).

The logger name for the Vaadin module is `com.holonplatform.vaadin`.

## 10. System requirements

### 10.1. Java

The Holon Platform Vaadin module requires Java 8 or higher.

### 10.2. Vaadin

The Holon Platform Vaadin module requires the Vaadin Flow platform version 12 or higher.