# Holon Platform Vaadin UI Module - Reference manual

version 5.4.0

Copyright © 2016-2018

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 Holon Vaadin module represents the platform support for the Vaadin web applications framework, focusing on the user interface components and data binding features.

This module provides integration with the platform foundation architecture, such as;

- The Property model and the Datastore API.

- The Holon Platform authentication and authentication architecture.

- The Holon Platform internationalization support.

This module provides a view navigation system which allows to create web applications focusing on the application functions, which can be represented by virtual pages, relying on a robust navigation architecture, with parameters and view lifecycle hooks support.

Furthermore, a complete set of fluent builders is available, to build web application UI components quickly and easily.

A complete integration with the Spring framework and Spring Boot is also available.

### 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.

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-bom</artifactId>
    <version>5.4.0</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-bom</artifactId>
          <version>5.4.0</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. What’s new in version 5.2.x

- Support for Spring version 5+ and Spring Boot 2.1+

- Support for JDK 9+ module system using `Automatic-Module-Name`.

## 4. What’s new in version 5.1.x

- Support for the the `PropertySet` identifier properties to make more easy and quick to setup data bound UI objects. See Items type and identifiers.

- Full support of Vaadin version 8.3, including for example the Navigator `@PushStateNavigation` strategy support.

- Better support for bean based data bound UI objects, with new builders and a Java API to create and configure the UI components just like the `Property` based one. See BeanListing.

- Support for components drag and drop configuration at Java API level. See Drag and Drop support.

- New component builder APIs for Vaadin `TabSheet` and `Accordion` components. See Component builders.

### 4.1. Migrating from version 5.0.x

#### 4.1.1. Deprecations

- PropertyListing builder API: dataSource(ItemDataProvider dataProvider, Property…​ identifierProperties). Since the `PropertySet` identifier properties support is used by default by the `PropertyListing` builder to obtain the item identifier properties, this method is no longer useful. To customize the item identifiers strategy, the more general `dataSource(ItemDataProvider dataProvider, ItemIdentifierProvider itemIdentifierProvider)` builder method can be used.

#### 4.1.2. Item identifiers in `Property` based Item listings

The `Property` based Item listing components now supports the PropertySet identifier properties configuration and use them as the default strategy to identify a `PropertyBox` type item.

So, when the `PropertySet` used with an item listing component declares one ore more identifier properties, there is no longer the need to declare the item identifier properties, for example, when configuring a `Datastore` based item data source. The identifier properties of the `PropertySet` will be used by default to provide the item identifier values.

For example, given the following Property model definition:

    private final static PathProperty<Long> ID = PathProperty.create("id", Long.class);
    private final static PathProperty<String> DESCRIPTION = PathProperty.create("description", String.class);

    private final static PropertySet<?> PROPERTIES = PropertySet.of(ID, DESCRIPTION);

A `PropertyListing` component, prior to version 5.1.0, had to be built this way, for example using a `Datastore` as item data source:

    Datastore datastore = getDatastore();

    PropertyListing listing = Components.listing.properties(PROPERTIES) (1)
        .dataSource(datastore, DataTarget.named("test"), ID) (2)
        .build();

1 | Provide the item listing `PropertySet`
2 | Configure a `Datastore` as item data source, providing the `ID` property as item identifier property

From version 5.1.x, the Property model definition can include the `PropertySet` identifier properties like this:

    private final static PathProperty<Long> ID = PathProperty.create("id", Long.class);
    private final static PathProperty<String> DESCRIPTION = PathProperty.create("description", String.class);

    private final static PropertySet<?> PROPERTIES = PropertySet.builderOf(ID, DESCRIPTION).withIdentifier(ID).build(); (1)

1 | Set the `ID` property as property set identifier property

And so the item identifier properties to use are no longer required during the `PropertyListing` component data source configuration, since the `PropertySet` identifier properties are used by default:

    Datastore datastore = getDatastore();

    PropertyListing listing = Components.listing.properties(PROPERTIES) (1)
        .dataSource(datastore, DataTarget.named("test")) (2)
        .build();

1 | The item listing `PropertySet` provides the property set identifier properties
2 | There is no longer the need to declare the `ID` property as item identifier property at data source configuration time, since the configured `PropertySet` identifier properties will be used by default

## 5. Vaadin UI integration

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

Maven coordinates:

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

## 6. Component builders

A complete set of fluent builders is available to create and configure the most common Vaadin components and the additional components provided by the Holon platform Vaadin module.

| See UI Components for a list of the additional components made available by the Holon platform Vaadin module.

All the builders can be obtained by using the Components API, which is organized in sub-APIs by components category.

The available component categories are the following:

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 standard Vaadin components, such as `Label`, `Button`, and standard layout components.
input | Builders for different data type `Input` components, including selection components. Furthermore, it provides builder to create input forms.
view | Builders for `ViewComponent` components and view forms.
listing | Builders for components which represent a list of items.

| For each UI displayed text of a component (for example, the component caption or description), the builders provide the opportunity to set a localizable text, using a `Localizable` object or directly providing the message code and the default message of the localizable text. In order for the localization to work, a `LocalizationContext` must be available as a context resource. See the Internationalization documentation for further information.

## 7. Component builders common features

The Holon Platform Vaadin component builders make available a set of common features, partly related to standard Vaadin features configuration and partly dedicated to the integration with some core Holon Platform APIs.

For each UI component which extends a standard Vaadin `Component` hierarchy, the builder APIs provide methods to configure all the component attributes and register the supported listeners. In addition to the common component configuration attributes, each component builder makes available methods to configure the component specific attributes and supported behaviors.

Label builder example

    Label lbl = Components.label() (1)
        .fullWidth() (2)
        .height(50, Unit.PIXELS) (3)
        .styleName("my-style").styleName(ValoTheme.LABEL_BOLD) (4)
        .icon(VaadinIcons.CHECK) (5)
        .caption("The caption") (6)
        .captionAsHtml() (7)
        .description("The description") (8)
        .withData(new MyData()) (9)
        .hidden() (10)
        .disabled() (11)
        .responsive() (12)
        .withAttachListener(event -> { (13)
          // ...
        }).withDetachListener(event -> { (14)
          // ...
        }).withContextClickListener(event -> { (15)
          event.isDoubleClick();
          // ...
        }).errorHandler(event -> { (16)

        })
        // Label specific configuration
        .content("Label content") (17)
        .html() (18)
        .build();

1 | Obtain a `com.vaadin.ui.Label` component builder
2 | Set the component width to `100%`
3 | Set the component height to `50px`
4 | Add two css style class names
5 | Set the component icon
6 | Set the caption
7 | Set the caption to be rendered as HTML
8 | Set the description (tooltip)
9 | Set a generic data value bound to the component
10 | Set the component as hidden (not visible)
11 | Set the component as disabled
12 | Set the component as responsive
13 | Register a `AttachListener`
14 | Register a `DetachListener`
15 | Register a `ContextClickListener`
16 | Set the component `ErrorHandler`
17 | Set the Label content
18 | Set the Label content mode as HTML

For component container component types (for example, Layout components), the builder APIs provides a set of methods to add components to the container to build, also providing layout configuration attributes such as alignment and expand ratio, when supported.

VerticalLayout builder example

    VerticalLayout verticalLayout = Components.vl() (1)
        .margin() (2)
        .spacing() (3)
        .add(COMPONENT_1).add(COMPONENT_2, COMPONENT_3) (4)
        .addAndAlign(COMPONENT_4, Alignment.TOP_CENTER) (5)
        .addAndExpand(COMPONENT_5, 0.5f) (6)
        .addAndExpandFull(COMPONENT_6) (7)
        .addAlignAndExpand(COMPONENT_7, Alignment.MIDDLE_CENTER, 1f) (8)
        .deferLocalization().build();

1 | Obtain a `com.vaadin.ui.VerticalLayout` component builder
2 | Enable layout margins
3 | Enable layout spacing
4 | Add components to the layout in given order
5 | Add a component and set the component alignment
6 | Add a component and set the component expand ratio
7 | Add a component and set the component expand ratio to 1 (full)
8 | Add a component and set the component alignment and expand ratio

### 7.1. Component configurators

When a component instance is already available, the Components API makes available a set of component configurator APIs, which can be used to configure a component instance, using the same API as the component builders.

The `configure(AbstractComponent component)` method can be used to obtain a component configurator for a generic `com.vaadin.ui.AbstractComponent`, to setup common component configuration attributes.

Other component confgurator APIs are provided to configure specific components, such a `Label` and `Button`, and the standard Vaadin layout components.

    Label label = new Label();

    Components.configure(label).fullWidth().content("my content").contentMode(ContentMode.PREFORMATTED); (1)

    VerticalLayout verticalLayout = new VerticalLayout();

    Components.configure(verticalLayout).spacing().addAndAlign(COMPONENT_1, Alignment.TOP_CENTER) (2)
        .addAndExpandFull(COMPONENT_2);

1 | Label component configurator
2 | VerticalLayout component configurator

### 7.2. Messages localization support

The component builder methods that can be used to configure a text to display for a component supports the message localization using the standard Holon Platform internationalization APIs.

The message localization attributes can be provided either using:

- A `Localizable` object instance;

- Or directly providing the message localization attributes, such as the message code, the default message and the optional message localization arguments.

A set of localizable message builder methods are available, for example, for standard Vaadin component attributes, such as the component caption and description.

    Button btn = Components.button().caption("DefaultCaption", "button.caption.code") (1)
        .build();

    Label lbl = Components.label()
        .content(Localizable.builder().message("DefaultMessage").messageCode("my.message.code").build()) (2)
        .build();

1 | Set the Button caption using a default caption message (`DefaultCaption`) and a message localization code (`button.caption.code`)
2 | Set a localizable Label content using a `Localizable`

| In order for the message localization to work, a valid `LocalizationContext` instance must be available as a context resource using the default `LocalizationContext` resource key (i.e. the `LocalizationContext` class name). See the LocalizationContext documentation for details about the `LocalizationContext` API and the Context resources documentation for information about the Holon Platform Context architecture.

| This module makes available a Vaadin session scope to use the Vaadin session as context resources scope.

#### 7.2.1. Defer localization

By default, the component messages localization is performed immediately during the component building, when a localizable message is provided at component configuration time.

Since the Holon Platform localization APIs require that a `LocalizationContext` resource is available to perform messages localization, when this is not possible the messages localization will not work at component configuration time. The `LocalizationContext` resource must be also localized, i.e. the current `Locale` is configured and available, in order to ensure messages localization support.

When the `LocalizationContext` resource configuration or localization availability is expected after the component build time, the component builder APIs provide a method to defer the component messages localization: `deferLocalization()`.

This method instructs the builder to resolve any message localization (for example the component caption and description) only when the component is attached to a parent layout, and this means only when the parent layout too is attached to the application UI.

    Label lbl = Components.label() //
        .caption("Default caption", "caption.message.code") //
        .deferLocalization() (1)
        .build();

1 | Set to defer the component messages localization at UI display time

### 7.3. Drag and Drop support

The Vaadin module component builders supports component drag and drop configuration, allowing to declare a component as draggable and configure the drag mode and attributes and to declare a component as a drop target providing the target configuration and logic to react to a drop event.

The standard Vaadin `DragSourceExtension` and `DropTargetExtension` extensions are used to configure components drag and drop capabilities.

The `dragSource` builder method can be used to declare a component as draggable. The provided `Consumer` can be used to configure the `DragSourceExtension` for the component.

The `dropTarget` builder method can be used to declare a component as a drop target and the provided `BiConsumer` can be used to configure the `DropTargetExtension` for the component and to obtain the actual component instance when a drop event occurs.

    Label lbl = Components.label().content("Draggable").dragSource(dragSource -> { (1)
      dragSource.setEffectAllowed(EffectAllowed.MOVE); (2)
      dragSource.setDataTransferText("hello receiver");
      dragSource.addDragStartListener(e -> Notification.show("Drag event started"));
    }).build();

    VerticalLayout droppableLayout = Components.vl().fullWidth().caption("Drop things inside me")
        .dropTarget((dropTarget, component) -> { (3)
          dropTarget.setDropEffect(DropEffect.MOVE); (4)
          dropTarget.addDropListener(dropEvent -> { (5)
            dropEvent.getDragSourceComponent().ifPresent(dragged -> component.addComponent(dragged));
            Notification.show("DropEvent with data transfer text: " + dropEvent.getDataTransferText());
          });
        }).build();

1 | Configure the Label as draggable
2 | The `DragSourceExtension` can be configured using the provided `Consumer` function
3 | Configure the VerticalLayout as a drop target
4 | The `DropTargetExtension` can be configured using the provided `BiConsumer` function
5 | The second argument of the `BiConsumer` function is the actual VerticalLayout instance, used in this case to add the dropped component to the layout when a drop event occurs

## 8. UI Components

The Vaadin module provides a set of additional UI components which can be used besides the standard Vaadin components.

### 8.1. Input

The Input interface represents a component that provides a user-editable value, which can be read and setted using the methods provided by the The ValueHolder API.

The `Input` API is parametrized on the value type it manages and the value management is provided by the ValueHolder API, which provides methods to:

- Set the Input value.

- Read the input value.

- Provide and empty value representation.

- Check whether a value is available.

- Listen to value changes registering one or more ValueChangeListener.

Furthermore, the `Input` API supports two component state configuration options:

- Read-only mode: When an `Input` is in read-only mode, the user can’t change the Input value.

- Required mode: When an `Input` is in required mode, a required indicator symbol is visible.

The `Input` API is a general and abstract representation of an UI object which holds a value, the actual Vaadin `Component` representation can be obtained though the `getComponent()` method and used with the standard Vaadin APIs.

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

    Component component = stringInput.getComponent(); (2)
    VerticalLayout vl = Components.vl().add(component).build(); (3)

1 | Create a String type input
2 | Get the actual Input `Component`
3 | Add the Input `Component` to a vertical layout

#### 8.1.1. Create an `Input` component

An `Input` component can be created using the Components API, through the input sub-interface methods.

A typed `Input` builder method is available for each available `Input` value type. Besides the base `Input` types, as set of methods are available to create single and multi select Input components. See Selectable Input for details.

    Input<String> stringInput = Components.input.string().build(); (1)
    stringInput = Components.input.string(true).build(); (2)
    Input<Integer> integerInput = Components.input.number(Integer.class).build(); (3)
    Input<Boolean> booleanInput = Components.input.boolean_().build(); (4)
    Input<Date> dateInput = Components.input.date(Resolution.DAY).build(); (5)
    Input<LocalDate> localDateInput = Components.input.localDate().build(); (6)
    Input<LocalDateTime> localDateTimeInput = Components.input.localDateTime().build(); (7)

    SingleSelect<MyEnum> enumSingleSelect = Components.input.enumSingle(MyEnum.class).build(); (8)
    MultiSelect<MyEnum> enumMultiSelect = Components.input.enumMulti(MyEnum.class).build(); (9)

1 | `String` type Input
2 | `String` type Input represented as a text area
3 | Numeric (`Integer` in this case) type Input
4 | `Boolean` type Input
5 | `Date` type Input with resolution configuration
6 | `LocalDate` type Input
7 | `LocalDateTime` type Input
8 | `Enum` type Input represented with a single select
9 | `Enum` type Input represented with a multi select

Input component configuration:

The `Input` builder API provides methods both for the `Input` attributes al listeners configuration and for the associated Input `Component` configuration, including API methods for specific `Input` and `Component` types.

    Input<String> stringInput = Components.input.string() //
        // Component configuration
        .fullWidth().styleName("my-style").caption("The caption") (1)
        // Input configuration
        .readOnly() (2)
        .tabIndex(10) (3)
        .withValue("Initial value") (4)
        .withValueChangeListener(event -> { (5)
          event.getValue();
          event.getOldValue();
          // ...
        }).withFocusListener(event -> { (6)
          // focused
        })
        // Specific String Input configuration
        .inputPrompt("The prompt") (7)
        .maxLength(100) (8)
        .blankValuesAsNull(true) (9)
        .textChangeEventMode(ValueChangeMode.BLUR) (10)
        .build();

1 | Input `Component` configur
2 | Set the Input as read-only
3 | Set the tabulator index
4 | Set the Input initial value
5 | Register a `ValueChangeListener`
6 | Register a `FocusListener`
7 | Set the Input prompt
8 | Set the String Input max length (the maximum number of cahracters)
9 | Set to treat blank String values (with 0 length or whitespaces only) as `null` values.
10 | Set the mode how the Input triggers vaue change events

See the next sections for details about the `Input` configuration attributes and features.

#### 8.1.2. Obtain an Input component from a `HasValue` Component

An `Input` component can be obtained from a standard Vaadin `HasValue` Component using the `from` static method of the `Input` API.

    TextField field = new TextField();

    Input<String> stringInput = Input.from(field); (1)

1 | Create a `String` type `Input` using a Vaadin `TextField` as concrete implementation

A `com.vaadin.data.Converter` can also be provided to obtain an `Input` component with a different value type from the original field type, providing the presentation to model type value conversion logic and vice-versa.

    TextField field = new TextField();

    Input<Integer> integerInput = Input.from(field, new StringToIntegerConverter("conversion error")); (1)

1 | Create a `Integer` type `Input` using a Vaadin `TextField` as concrete implementation and providing a `Converter` to convert `String` type presentation values into `Integer` type model values and vice-versa

#### 8.1.3. Obtain a `HasValue` Component from Input builders

The `Input` builder APIs can provide the `Input` instance also a standard Vaadin `HasValue` Component, which is represented by the convenience Field interface.

To obtain a `Field` type Input component, the `Input` builder API `asField()` method can be used.

    Field<LocalDate> field = Components.input.localDate() (1)
        // configuration omitted
        .asField(); (2)

    HasValue<LocalDate> hasValue = field; (3)
    Component component = field;

1 | Obtain a `LocalDate` type `Input` builder
2 | Get the `Input` component as a `LocalDate` type `Field`
3 | The obtained `Field` is a `HasValue<LocalDate>` and a `Component`

#### 8.1.4. Input value conversion

The `Input` interface makes available a set of methods to create an `Input` from another `Input` or from a standard Vaadin `HasValue` Component with a different value type, providing a suitable converter to perform value conversions from the presentation value type to the model value type and vice-versa.

The stardard Vaadin `com.vaadin.data.Conveter` API is supported to provide the value conversion logic.

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

    Input<Integer> integerInput = Input.from(stringInput, new StringToIntegerConverter("Conversion error")); (1)

    Input<Boolean> booleanInput = Input.from(integerInput, (2)
        Converter.from(value -> Result.ok((value == null) ? Boolean.FALSE : (value.intValue() > 0)),
            value -> (value == null) ? null : (value ? 1 : 0)));

    Input<Long> longInput = Input.from(new TextField(), new StringToLongConverter("Conversion error")); (3)

1 | Convert a `String` presentation type `Input` into a `Integer` model type `Input` using the standard Vaadin `StringToIntegerConverter`
2 | Obtain a Boolean type `Input` from the `Integer` type one providing the value conversion logic
3 | Obtain a `Long` type `Input` from a `String` type `TextField` using the `StringToLongConverter` converter

Besides the standard Vaadin `com.vaadin.data.Conveter`, the Holon `PropertyValueConverter` can be used, providing the `Property` to which the converter is bound.

| See the Property value conversion documentation for information about the `PropertyValueConverter` API.

    Input<Integer> integerInput = Components.input.number(Integer.class).build();

    final Property<Boolean> BOOL_PROPERTY = PathProperty.create("bool", Boolean.class); (1)

    Input<Boolean> booleanInput = Input.from(integerInput, BOOL_PROPERTY,
        PropertyValueConverter.numericBoolean(Integer.class)); (2)

1 | The `Boolean` type `Property` to use for the `PropertyValueConverter`
2 | Create a `Boolean` type `Input` from an `Integer` type `Input`, using a the default numericBoolean `PropertyValueConverter`

#### 8.1.5. Listening to `Input` value changes

The `Input` API supports ValueChangeListener registration to listen to `Input` value changes.

The value change event provide the current (changed) `Input` value, the previous (old) `Input` value, the value change source (i.e. the reference to the `Input` component which triggered the value change listeners) and whether the value change was originated by a user action or from server side code.

    Input<String> stringInput = Components.input.string() //
        .withValueChangeListener(event -> { (1)
          String currentValue = event.getValue(); (2)
          String previousValue = event.getOldValue(); (3)
          boolean byUser = event.isUserOriginated(); (4)
          ValueHolder<String> source = event.getSource(); (5)
          // ...
        }).build();

1 | Register a `ValueChangeListener` for the `String` type `Input`
2 | Get the new value that triggered the value change event
3 | Get the value of the `Input` before the value change event occurred
4 | Get whether the event was triggered by user interaction, on the client side, or programmatically, on the server side
5 | Get the source of the value change event, i.e. the `Input` component itself

Value change mode

The mode and the frequency with which the value change events are triggered can be customized for the `Input` components which supports it.

The MaySupportValueChangeMode API, extended by the `Input` API, allows to check if the value change mode configuration is supported by a specific `Input` component through the `isValueChangeModeSupported()` method.

If so, the value change mode can be configured specifying:

- The `com.vaadin.shared.ui.ValueChangeMode` enumeration value which represents when and how often `Input` value changes are transmitted from the client to the server.

- Set the value change timeout, i.e. how often value change events are triggered, when the `ValueChangeMode` is either `LAZY` or `TIMEOUT`.

    Input<String> stringInput = Components.input.string().withValueChangeListener(event -> {
      // ...
    }).valueChangeMode(ValueChangeMode.LAZY) (1)
        .valueChangeTimeout(1000) (2)
        .build();

    boolean supported = stringInput.isValueChangeModeSupported(); (3)
    if (supported) {
      stringInput.setValueChangeMode(ValueChangeMode.BLUR); (4)
    }

1 | Configure the `ValueChangeMode` using the Input builder. The builder methods to configure the value change mode are available only for Input components which support it.
2 | Configure the value change timeout using the Input builder
3 | Check if the value change mode configuration is supported by the `Input` component
4 | Set the value change mode to `BLUR` using the `Input` API

### 8.2. ValidatableInput

The ValidatableInput interface represents an `Input` component which supports value validation using the standard Holon Platform Validator API.

A `ValidatableInput` can be obtained in the following ways:

1. From an existing `Input` or `HasValue` component: Using the `from` static method of the `ValidatableInput` API.

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

    ValidatableInput<String> validatableInput = ValidatableInput.from(stringInput); (1)

    validatableInput = ValidatableInput.from(new TextField()); (2)

1 | Create a `ValidatableInput` from a String Input
2 | Create a `ValidatableInput` from a `TextField`

2. Using the `Input` builder: Using the `validatable()` builder method, which returns a `ValidatableInputBuilder` API that can be used to configure the `ValidatableInput`, for example adding one or more `Validator`, before returning it.

    validatableInput = Components.input.string() //
        .caption("The caption") //
        .validatable() (1)
        .required("Value is required") (2)
        .withValidator(Validator.max(100)) (3)
        .build();

1 | Get the builder API to obtain a `ValidatableInput`
2 | Add a default required (the input is not empty) validator using the provided error message
3 | Add a `Validator

#### 8.2.1. Registering Validators and perform validation

The `addValidator` method of the `ValidatableInput` API can be used to register value validators for the `Input` component.

The `Validator` API can be used to obtain a set of builtin validators, allowing to specify the validation error message, even using a localizable message code. See the Holon Platform Validator API for details.

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

    validatableInput.addValidator(Validator.max(100)); (2)
    validatableInput.addValidator(Validator.email("Must be a valid e-mail address", "invalid.email.message.code")); (3)
    validatableInput
        .addValidator(Validator.create(value -> value.length() >= 3, "Must be at least 3 characters long")); (4)

1 | Create a `String` type `ValidatableInput`
2 | Add a builtin `Validator` to check the Input value is maximum 100 characters long, using the default validation error message
3 | Add a builtin `Validator` to check the Input value is a valid e-mail address, providing a localizable validation error message
4 | Add a `Validator` to check the Input value is at least 3 characters long and provide the validation error message

The actual value validation can be performed using the Validatable API, which provides the following methods:

- `validate()`: Validate the current `Input` value using the registered `Validator` s. Throws a `ValidationException` if the value is not valid, which provides the validation error message/s. The `ValidationException` is `Localizable`, providing optional message code and arguments for validation message localization.

- `isValid()`: Returns whether the current `Input` value is valid, swallowing any `ValidationException`.

    try {
      validatableInput.validate(); (1)
    } catch (ValidationException e) {
      // do something at validation failure
    }

    boolean valid = validatableInput.isValid(); (2)

1 | Validate the `Input` value. The `ValidationException` is thrown if the validation fails.
2 | Checks whether the current `Input` value is valid, swallowing any `ValidationException`.

#### 8.2.2. Automatic validation at `Input` value change

Value validation can be automatically triggered each time the `Input` value changes.

To enable this behaviour, either the `setValidateOnValueChange` method of the `ValidatableInput` API or the `validateOnValueChange` method of the `ValidatableInput` builder API can be used.

    ValidatableInput<String> validatableInput = Components.input.string().validatable() //
        .validateOnValueChange(true) (1)
        .build();

    validatableInput.setValidateOnValueChange(false); (2)

1 | Use the `ValidatableInput` builder API to enable the automatic value validation at `Input` value change
2 | Use the `ValidatableInput` API to disable the the automatic value validation at `Input` value change

#### 8.2.3. Validation errors notification

By default, the standard Vaadin component error notification is used to notify validation errors on `ValidatableInput` components. As per default behaviour, an invalid component is decorated with a proper CSS style class (for example to show a red border around the component itself) and the validation error is notified using a tooltip.

To change this behavior and to control how the validation errors are notified to the user, the ValidationStatusHandler API can be used.

A `ValidationStatusHandler` listens to validation status change events and the provided validation event can be used to:

- Obtain the current component validation status: `UNRESOLVED` (no value validation has been made yet), `VALID` (validation passed), `INVALID` (validation failed).

- Obtain the current validation error messages if the component is in the `INVALID` status. The error messages can be obtained as `Localizable` to support message localization.

- Get the source component against whom the validation was performed.

The `ValidationStatusHandler` can be configured either using the `setValidationStatusHandler` method of the `ValidatableInput` API or the `validationStatusHandler` method of the `ValidatableInput` builder API.

    ValidatableInput<String> validatableInput = Components.input.string().validatable() //
        .validationStatusHandler(event -> { (1)
          Status status = event.getStatus();
          // ....
        }).build();

    validatableInput.setValidationStatusHandler(event -> { (2)
      event.getError();
      // ...
    });

1 | Use the `ValidatableInput` builder API to configure a `ValidationStatusHandler`
2 | Use the `ValidatableInput` API to configure a `ValidationStatusHandler`

The `ValidationStatusHandler` also provides static methods to obtain a default validation status handler either using a `Label` component or a Vaadin `Notification` component.

    Label statusLabel = new Label();
    ValidationStatusHandler vsh = ValidationStatusHandler.label(statusLabel); (1)

    ValidationStatusHandler usingNotifications = ValidationStatusHandler.notification(); (2)

1 | Create a `ValidationStatusHandler` using a `Label` to display validation errors.
2 | Create a `ValidationStatusHandler` using a `Notification` to notify validation errors.

### 8.3. Selectable Input

When the Input values must be selected from a specific set, a selectable `Input` type can be used. Two selectable Input types are available:

- The SingleSelect Input, in which at most one item can be selected at a time;

- The MultiSelect Input, in which multiple items can be selected at the same time.

Both selectable `Input` types extends the Selectable API, which provides methods to check if some item is selected, obtain the selected item/s and change the current selection.

A selectable `Input` can be obtained using the Components API, through the `singleSelect` and `multiSelect` methods and their specializations.

Furthermore, a SelectionListener can be registered to listen to selection changes.

SingleSelect example

    SingleSelect<TestData> singleSelect = Components.input.singleSelect(TestData.class) (1)
        .caption("Single select").build();

    singleSelect.setValue(new TestData(1)); (2)
    singleSelect.select(new TestData(1)); (3)

    singleSelect.clear(); (4)
    singleSelect.deselectAll(); (5)

    boolean selected = singleSelect.isSelected(new TestData(1)); (6)

    singleSelect.addSelectionListener(
        s -> s.getFirstSelectedItem().ifPresent(i -> Notification.show("Selected: " + i.getId()))); (7)

1 | Create a `SingleSelect` Input using the `TestData` class as selection item type
2 | Select a value using the default `setValue()` Input method
3 | Select a value using `select()` method
4 | Deselect the value using the default `clear()` Input method
5 | Deselect the value using the `deselectAll()` method
6 | Check whether a value is selected
7 | Add a selection listener

MultiSelect example

    MultiSelect<TestData> multiSelect = Components.input.multiSelect(TestData.class) (1)
        .caption("Multi select").build();

    Set<TestData> values = new HashSet<>();
    values.add(new TestData(1));
    values.add(new TestData(2));

    multiSelect.setValue(values); (2)
    multiSelect.select(new TestData(3)); (3)

    multiSelect.deselect(new TestData(3)); (4)

    multiSelect.clear(); (5)
    multiSelect.deselectAll(); (6)

    boolean selected = multiSelect.isSelected(new TestData(1)); (7)

    multiSelect.addSelectionListener(s -> Notification.show(s.getAllSelectedItems().stream()
        .map(i -> String.valueOf(i.getId())).collect(Collectors.joining(";", "Selected: ", "")))); (8)

1 | Create a `MultiSelect` Input using the `TestData` class as selection item type
2 | Select a set of values using the default `setValue()` Input method
3 | Add a value to current selection using the `select()` method
4 | Remove a value from current selection
5 | Deselect the value using the default `clear()` Input method
6 | Deselect the value using the `deselectAll()` method
7 | Check whether a value is selected
8 | Add a selection listener

#### 8.3.1. Rendering mode

The visual aspect of the selectable Input can be configured using the `RenderingMode` enumeration. According to the rendering mode, a suitable UI component will be used to implement the Input.

| The default rendering modes are `SELECT` for `SingleSelect` inputs and `OPTIONS` for `MultiSelect` inputs.

Rendering mode | SingleSelect UI component | MultiSelect UI component
--- | --- | ---
NATIVE_SELECT | `com.vaadin.ui.NativeSelect` | not supported
SELECT | `com.vaadin.ui.ComboBox` | `com.vaadin.ui.ListSelect`
OPTIONS | `com.vaadin.ui.CheckBoxGroup` | `com.vaadin.ui.RadioButtonGroup`

    SingleSelect<TestData> singleSelect = Components.input.singleSelect(TestData.class, RenderingMode.OPTIONS) (1)
        .build();

    MultiSelect<TestData> multiSelect = Components.input.multiSelect(TestData.class, RenderingMode.SELECT) (2)
        .build();

1 | Create a `SingleSelect` using the OPTIONS rendering mode: a `CheckBox` group UI component will be used
2 | Create a `MultiSelect` using the SELECT rendering mode: a `ListSelect` UI component will be used

#### 8.3.2. Using selectable Inputs for Enumerations

The Components API provides convenience methods to build a selectable `Input` using the values of an enumeration as selection items.

The enumeration selectable `Input` can be obtained either as a single select or a multiple select, even specifying the `RenderingMode` to use.

    SingleSelect<MyEnum> singleSelect = Components.input.enumSingle(MyEnum.class).build(); (1)
    singleSelect = Components.input.enumSingle(MyEnum.class, RenderingMode.NATIVE_SELECT).build(); (2)

    MultiSelect<MyEnum> multiSelect = Components.input.enumMulti(MyEnum.class).build(); (3)

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

#### 8.3.3. Selection items data source

The data source of the available items for a selectable `Input` can be configured in the following ways:

- Using a fixed set of items, which can be provided using the `addItem(…​)` or `items(…​)` methods of the select input builder.

- Using a Holon Platform ItemDataProvider.

- Using a standard Vaadin `DataProvider`.

    SingleSelect<TestData> singleSelect = Components.input.singleSelect(TestData.class)
        .items(new TestData(1), new TestData(2)) (1)
        .build();

    singleSelect = Components.input.singleSelect(TestData.class)
        .dataSource(ItemDataProvider.create(q -> 2, (q, o, l) -> Stream.of(new TestData(1), new TestData(2)))) (2)
        .build();

    singleSelect = Components.input.singleSelect(TestData.class)
        .dataSource(DataProvider.ofItems(new TestData(1), new TestData(2))) (3)
        .build();

1 | Create a select input using an explicitly provided items set
2 | Create a select input using a Holon platform `ItemDataProvider`
3 | Create a select input using a Vaadin `DataProvider`

#### 8.3.4. Item captions and icons

The selectable input builders allow to explicitly set the selection item captions and icons. For the items caption configuration, the Holon Platform localization architecture is supported, and the builders provide methods to specify the captions using a `Localizable` object or a message code.

See Messages localization support for details about messages localization.

    final TestData ONE = new TestData(1);
    final TestData TWO = new TestData(2);

    SingleSelect<TestData> singleSelect = Components.input.singleSelect(TestData.class).items(ONE, TWO)
        .itemCaption(ONE, "One") (1)
        .itemCaption(ONE, "One", "caption-one-message-code") (2)
        .itemIcon(ONE, VaadinIcons.STAR) (3)
        .build();

1 | Set the item caption for the `ONE` item
2 | Set the localizable item caption for the `ONE` item, providing a default caption and a translation message code
3 | Set the item icon for the `ONE` item

Furthermore, the `ItemCaptionGenerator` and the `ItemIconGenerator` interfaces can be used to provide custom selection items captions and icons.

By default, the item caption is obtained using the `toString()` method of the item class and no icon is displayed.

    SingleSelect<TestData> singleSelect = Components.input.singleSelect(TestData.class)
        .items(new TestData(1), new TestData(2)) // set the items
        .itemCaptionGenerator(i -> i.getDescription()) (1)
        .itemIconGenerator(i -> i.getId() == 1 ? VaadinIcons.STAR : VaadinIcons.STAR_O) (2)
        .build();

1 | Set an item caption generator which provides the item description as item caption
2 | Set an item icon generator

#### 8.3.5. `SingleSelect` caption filter

For the `SingleSelect` type Inputs which use the SELECT rendering mode, the UI component allows the user to type a filtering text to search for a selection item, and such filter by default is referred to item captions.

When using a fixed item set, the in-memory caption filter can be customized using the `filteringMode(…​)` builder method.

    SingleSelect<TestData> singleSelect = Components.input.singleSelect(TestData.class)
        .items(new TestData(1), new TestData(2)) // set the items
        .filteringMode(
            (itemCaption, filterText) -> itemCaption.toLowerCase().startsWith(filterText.toLowerCase())) (1)
        .build();

When using a `ItemDataProvider` or a Vaadin `DataProvider`, an overloaded form of the `dataSource(…​)` method can be used, which accept as second parameter a function to provide a suitable query filter using the current user filtering text.

    final TestData ONE = new TestData(1);
    final TestData TWO = new TestData(2);

    SingleSelect<TestData> singleSelect = Components.input.singleSelect(TestData.class)
        .dataSource(ItemDataProvider.create(q -> 2, (q, o, l) -> Stream.of(ONE, TWO)), filterText -> QueryFilter
            .startsWith(ConstantConverterExpression.create("description"), filterText, true))
        .build();

#### 8.3.6. Using the `Property` model with selectable Inputs

The Holon platform Property model is fully supported by the selectable Input builders, which allows to create selectable Inputs using `PropertyBox` type items and a specific `Property` as selection property (typically, the property which acts as item id).

The selection data type will be the same as the selection property type.

The simplest way to configure a `Property` based selectable input, is by using a Datastore.

    Datastore datastore = obtainDatastore();

    final PathProperty<Long> ID = PathProperty.create("id", Long.class);
    final PathProperty<String> DESCRIPTION = PathProperty.create("description", String.class);

    SingleSelect<Long> singleSelect = Components.input.singleSelect(ID) (1)
        .dataSource(datastore, DataTarget.named("testData"), PropertySet.of(ID, DESCRIPTION)) (2)
        .itemCaptionGenerator(propertyBox -> propertyBox.getValue(DESCRIPTION)) (3)
        .build();

    singleSelect.setValue(Long.valueOf(1)); (4)
    Long selectedId = singleSelect.getValue(); (5)

    singleSelect.refresh(); (6)

1 | Create a `SingleSelect` using the `ID` property as selection property
2 | Set the select data source using a `Datastore`, specifying the `DataTarget` and the set of property to use as query projection
3 | Set an item caption generator which provides the value of the `DESCRIPTION` property as item caption
4 | Set the selected value, which will be of type `Long`, consistent with the `ID` selection property
5 | Get the selected value, which will be of type `Long`, consistent with the `ID` selection property
6 | Refresh the selection items, querying the `Datastore`

One or more `QueryConfigurationProvider` can be used to control the `Datastore` query configuration, providing additional query filters and/or sorts.

    Datastore datastore = obtainDatastore();

    final PathProperty<Long> ID = PathProperty.create("id", Long.class);
    final PathProperty<String> DESCRIPTION = PathProperty.create("description", String.class);

    SingleSelect<Long> singleSelect = Components.input.singleSelect(ID)
        .dataSource(datastore, DataTarget.named("testData"), PropertySet.of(ID, DESCRIPTION), // Datastore
            () -> ID.gt(0L)) (1)
        .itemCaptionGenerator(propertyBox -> propertyBox.getValue(DESCRIPTION)).build();

1 | Set a `QueryConfigurationProvider` which provides a `QueryFilter` to select only the items with the `ID` property that is greater than 0

##### Selection model converter

When the Holon platform `Property` model is used for selectable Inputs and the selection value type is not a `PropertyBox`, i.e. the selection items are not of the same type of the `Input` value type, a conversion function is required to obtain the `PropertyBox` item from a selection value when the value is setted in the Input component, either using `setValue(…​)` or `select(…​)`.

For example, if a `String` type `Property` is declared as selection property, the `Input` value will be the the value of the selection property (of `String` type), while the selection items are `PropertyBox`.

When a `Datastore` is provided as the data source of the select, a default item converter is configured. The default item converter tries to obtain the `PropertyBox` item by performing a query on the `Datastore` and using a filter predicate to get the item for which the selection property value is equal to the value to select, assuming that the selection property acts as primary key.

To change the default conversion strategy, a custom item converter can be provided to the select input builder using the `itemConverter(…​)` method:

    Datastore datastore = obtainDatastore();

    final PathProperty<Long> ID = PathProperty.create("id", Long.class);
    final PathProperty<String> DESCRIPTION = PathProperty.create("description", String.class);
    final DataTarget<?> TARGET = DataTarget.named("testData");
    final PropertySet<?> PROPERTIES = PropertySet.of(ID, DESCRIPTION);

    SingleSelect<Long> singleSelect = Components.input.singleSelect(ID)
        .dataSource(datastore, DataTarget.named("testData"), PROPERTIES)
        .itemConverter(
            value -> datastore.query().target(TARGET).filter(ID.eq(value)).findOne(PROPERTIES).orElse(null)) (1)
        .build();

1 | Set an `ItemConverter` providing the query to perform to obtain the item `PropertyBox` from the selection `ID` property value

### 8.4. Input groups

The PropertyInputGroup component allows to group and manage a set of `Input` fields, relying on the `Property` model and using `PropertyBox` objects to collect, set and provide the Input values.

| See the Property documentation for further information about the Holon Platform `Property` model.

A `PropertyInputGroup` is bound to a set of properties, and for each property an `Input` field is made available to set and get the property value. Each property has to be bound to an `Input` field with a consistent value type.

#### 8.4.1. Property Inputs rendering

By default, the Holon platform Property rendering architecture is used to automatically generate a suitable `Input` component for each `Property` of Input group property set, according to the `Property` type.

The `Input` type is used as target rendering type to generate the `Input` components.

| See Property renderers and presenters for further information about Property renderers.

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

    final PropertySet<?> PROPERTIES = PropertySet.of(ID, DESCRIPTION);

    PropertyInputGroup group = Components.input.propertyGroup().properties(PROPERTIES) (1)
        .build();

1 | Configure the input group property set. The property `Input` fields are automatically generated using the available Property Rendereres from the default registry

#### 8.4.2. Explicit `Input` and `HasValue` binding

To explicitly set the `Input` component to use for a `Property` of the input group property set, the `bind(…​)` builder methods of the `PropertyInputGroup` builder API can be used.

The `bind(…​)` builder method can therefore be used to override the default property `Input` generation only when a custom `Input` type is required.

The standard `HasValue` Components are also supported to define a `Property` binding.

    PropertyInputGroup group = Components.input.propertyGroup().properties(PROPERTIES)
        .bind(ID, Components.input.number(Long.class).build()) (1)
        .bind(DESCRIPTION, new TextField()) (2)
        .build();

1 | Bind the `ID` property to a `Long` type `Input` component
2 | Bind the `DESCRIPTION` property to a `TextField`

#### 8.4.3. Input value convertes

When an `Input` component or `HasValue` component must be bind to a Property with a different type, a value converter can be provided to convert the Input value to the required Property type and vice-versa.

Specialized `bind` methods of the `PropertyInputGroup` builder API are available to use a standard Vaadin `com.vaadin.data.Converter` to provide the conversion logic.

    PropertyInputGroup group = Components.input.propertyGroup().properties(PROPERTIES)
        .bind(ID, Components.input.string().build(), new StringToLongConverter("Conversion error")) (1)
        .bind(ID, new TextField(), new StringToLongConverter("Conversion error")) (2)
        .build();

1 | Bind the `ID` property to a `String` type `Input` component and use a `StringToLongConverter` to convert the String values to the required `Long` property type
2 | Bind the `ID` property to a `TextField` and use a `StringToLongConverter` to convert the String values to the required `Long` property type

#### 8.4.4. Manage the property values using a `PropertyBox`

The property values are setted and obtained using the `PropertyBox` data container, using the same property set of the input group.

The property values are automatically updated in the current `PropertyBox` according to any user modification made through the Input’s UI components.

The property input group supports `ValueChangeListener` registration to be notified when the group `PropertyBox` value changes.

    PropertyInputGroup group = Components.input.propertyGroup().properties(PROPERTIES).build();

    group.setValue(PropertyBox.builder(PROPERTIES).set(ID, 1L).set(DESCRIPTION, "TestDescription").build()); (1)

    PropertyBox value = group.getValue(); (2)

    group.addValueChangeListener(e -> { (3)
      PropertyBox changedValue = e.getValue();
    });

1 | Set the input group property values using a `PropertyBox` with a matching property set
2 | Get the input group property values as a `PropertyBox` instance
3 | Add an input group value change listener

#### 8.4.5. Read-only properties

A property can be setted as read-only, to prevent the modification of its value. When a property is read-only, the `Input` component will be in read-only mode too, preventing the user from changing the value.

    PropertyInputGroup group = Components.input.propertyGroup().properties(PROPERTIES) //
        .readOnly(ID) (1)
        .build();

1 | The `ID` property is setted as read-only, preventing the user from changing the property value

#### 8.4.6. Hidden properties

A property can be setted as hidden. When a property is hidden, it is part of the group property set and its value will be preserved in the `PropertyBox` instances, but no `Input` component will be generated and bound to the property itself, so its value will never be visible on the user interface.

Inputs bound to hidden properties are never returned from the `PropertyInputGroup` methods which allow to inspect the available binding, such as `getInputs()`, `getInput(Property<T> property)` or `stream()`.

The `hidden(Property property)` method of the group builder can be used to set a property as hidden.

    PropertyInputGroup group = Components.input.propertyGroup().properties(PROPERTIES) //
        .hidden(ID) (1)
        .build();

1 | The `ID` property is setted as hidden and will not be displayed nor managed by the input group

#### 8.4.7. Default property values

A default value can be provided for a property. If available, the default value will be used as property value when the corresponding `Input` component is empty (i.e. has no value).

The `defaultValue(Property<T> property, DefaultValueProvider<T> defaultValueProvider)` method of the group builder can be used to set a default value for a property.

    PropertyInputGroup group = Components.input.propertyGroup().properties(PROPERTIES) //
        .defaultValue(DESCRIPTION, property -> "Default") (1)
        .build();

1 | Use a `DefaultValueProvider` to provide the `DESCRIPTION` property default value

### 8.5. Input group validation

A `PropertyInputGroup` support both property values and group value validation, supporting both the Holon Platform `Validator` API and the standard Vaadin validators.

When a validator in bound to the overall Input group, the value to validate will be represented by the `PropertyBox` type, which contains all the current property values.

    PropertyInputGroup group = Components.input.propertyGroup().properties(PROPERTIES) //
        .withValidator(DESCRIPTION, Validator.max(100)) (1)
        .withValidator(ID, com.vaadin.data.Validator.from(id -> id != null, "Id must be not null")) (2)
        // group validation
        .withValidator(Validator.create(propertyBox -> propertyBox.getValue(ID) > 0,
            "The ID value must be greater than 0")) (3)
        .build();

1 | Add a `Validator` bound to the `DESCRIPTION` property to check that the value size is not greater than 100 characters
2 | Add a `com.vaadin.data.Validator` to check the `ID` property value is not null
3 | Add an overall (group) `Validator` which reads the `ID` property value from the group `PropertyBox` value and checks it is greater than 0

Furthermore, a set of `required(…​)` group builder methods are provided to add a required validator to a property (i.e. a validator that check the value is not `null` or empty) and to show the required indicator symbol along with the property `Input` component.

    PropertyInputGroup group = Components.input.propertyGroup().properties(PROPERTIES) //
        .required(ID) (1)
        .required(ID, "The ID value is required") (2)
        .build();

1 | Add a required validator to the `ID` property
2 | Add a required validator to the `ID` property providing a custom validation error message

The input group validation can be requested using the `validate()` and it is performed by invoking:

1. All the available `Property` validators for each property of the input group property set;

2. Then the overall group validators, if any.

Besides the `validate()` method, the input group validation is performed by default when the Input group `PropertyBox` value is requested using the `getValue()` method. To skip the group validation when requesting the Input group value, a `getValue(boolean validate)` method is available and `false` can be specified for the validate parameter.

A further `getValueIfValid()` method can be used to obtain the Input group value only when it is valid, after performing the validations. If validation fails, an empty `Optional` is returned.

    PropertyInputGroup group = createInputGroup();

    try {

      group.validate(); (1)

      PropertyBox value = group.getValue(); (2)

    } catch (ValidationException e) {
      // validation failed
    }

    PropertyBox value = group.getValue(false); (3)

    group.getValueIfValid().ifPresent(propertyBox -> { (4)
      // ...
    });

1 | Explicit group validation: if some kind of validation failure occurs, a `ValidationException` is thrown
2 | Using the default `getValue()` method, the validation is triggered automatically, and a `ValidationException` is thrown if validation fails
3 | The `getValue(boolean validate)` method can be used to skip value validation
4 | The `getValueIfValid()` returns an `Optional`, which contains the `PropertyBox` value only if the validation succeded

#### 8.5.1. `Property` validators

Since the Property API supports direct validators registration for each `Property` instance, the property validators are inherited by default as Input group validators for each Property of the Input group property set.

This behavior can be disabled using the `ignorePropertyValidation()` method of the `PropertyInputGroup` builder API.

    PropertyInputGroup group = Components.input.propertyGroup().properties(PROPERTIES) //
        .ignorePropertyValidation() (1)
        .build();

1 | Set to ignore any Property `Validator` when binding the property to an `Input` component, i.e. to not inherit property validators when the property-Input binding is performed.

#### 8.5.2. Validation configuration

The Input group provides some configuration options to tune the validation strategy. The validation configuration can be controlled through the `PropertyInputGroup` builder API in order to:

- Enable or disable the automatic `Input` validation when the Input value changes (this behavior is enabled by default).

- Whether to stop property validation at first validation failure. When active, only the first `ValidationException` is thrown. Otherwise, a `ValidationException` which groups all the occurred validation exceptions is thrown, providing all the validation error messages (the default behavior).

- Whether to stop overall group validation at first validation failure. When active, only the first `ValidationException` is thrown. Otherwise, a `ValidationException` which groups all the occurred validation exceptions is thrown, providing all the validation error messages (the default behavior).

    PropertyInputGroup group = Components.input.propertyGroup().properties(PROPERTIES) //
        .validateOnValueChange(false) (1)
        .stopValidationAtFirstFailure(true) (2)
        .stopOverallValidationAtFirstFailure(true) (3)
        .build();

1 | Disable the automatic validation at `Input` value change
2 | Stop property validation at first validation failure
3 | Stop overall group validation at first validation failure

#### 8.5.3. Validation errors notification

A ValidationStatusHandler can be used to control how the validation errors are notified to the user, listening to validation status change events of the `PropertyInputGroup`.

See Validation errors notification for details about the `ValidationStatusHandler` API.

The property input group supports `ValidationStatusHandler` configuration both for property and overall validation.

    Label statusLabel = new Label();

    PropertyInputGroup group = Components.input.propertyGroup().properties(PROPERTIES) //
        .validationStatusHandler(validationEvent -> { (1)
          // ...
        }).propertiesValidationStatusHandler(validationEvent -> { (2)
          // ...
        }).validationStatusHandler(statusLabel) (3)
        .build();

1 | Configure a `ValidationStatusHandler` for the overall (group) validation
2 | Configure a `ValidationStatusHandler` for the properties validation
3 | Convenience method to use a `Label` as validation status handler

### 8.6. Handling value changes

The `PropertyInputGroup` builder API provides methods to register one or more `ValueChangeListener` in order to:

- Listen to `Input` value changes for the `Input` components bound to group property set.

- Listen to the Input group value changes, where the value type is represented by the `PropertyBox` type.

Furthermore, the `PropertyInputGroup` builder API makes available a set of methods to configure the value change notification strategy, i.e. the mode and the frequency with which the value change events are triggered, both for property level and group level value change events.

    PropertyInputGroup group = Components.input.propertyGroup().properties(PROPERTIES) //
        .withValueChangeListener(e -> { (1)
          PropertyBox value = e.getValue();
          // ...
        }).withValueChangeListener(DESCRIPTION, e -> { (2)
          String description = e.getValue();
          // ...
        }) //
        .valueChangeMode(ValueChangeMode.BLUR) (3)
        .valueChangeMode(DESCRIPTION, ValueChangeMode.LAZY) (4)
        .valueChangeTimeout(DESCRIPTION, 500) (5)
        .build();

1 | Add an overall value change listener
2 | Add a value change listener to the `Input` bound to the `DESCRIPTION` property
3 | Set the default `ValueChangeMode` for all inputs
4 | Set the `ValueChangeMode` only for the `Input` bound to the `DESCRIPTION` property
5 | Set the value change timeout to 500 ms only for the `Input` bound to the `DESCRIPTION` property

In addition to the standard `ValueChangeListener`, the PropertyInputValueChangeListener interface is also supported to listen to Property/Input pairs value changes.

The `PropertyInputValueChangeListener` provides the current `PropertyInputBinder` reference, besides of the standard `ValueChangeEvent`. The `PropertyInputBinder` makes available several methods to inspect the input group to which the value change source belongs, for example in order to obtain the values of other `Input` components.

    PropertyInputGroup group = Components.input.propertyGroup().properties(PROPERTIES) //
        .withValueChangeListener(DESCRIPTION, (event, binder) -> { (1)
          String description = event.getValue();
          Long id = binder.requireInput(ID).getValue();
          // ...
        }).build();

1 | Add a `PropertyInputValueChangeListener` to the Input bound to the `DESCRIPTION` property, which provides the current `PropertyInputBinder` to inspect all available group Inputs

### 8.7. Dealing with Virtual properties

By default, the `PropertyInputGroup` renders as an Input all the properties of the property set that has been provided at build time, including any VirtualProperty.

Since a `VirtualProperty` is a read-only property, the `Input` bound to a `VirtualProperty` is configured in read-only mode by default.

If the `VirtualProperty` value is calculated using the values of other properties of the `PropertyInputGroup` property set, can be useful to refresh the displayed `Input` value bound to the virtual property when one or more property of set changes.

For this purpose, the `refresh(…​)` methods of the `PropertyInputGroup` can be used. This methods are available from the `PropertyInputBinder` super-interface. You can refresh a specific property or all the properties of the set, even only the read-only ones.

    final VirtualProperty<String> VIRTUAL = VirtualProperty.create(String.class,
        propertyBox -> propertyBox.getValue(ID) + " -" + propertyBox.getValue(DESCRIPTION));

    final PropertySet<?> PROPERTIES = PropertySet.of(ID, DESCRIPTION, VIRTUAL);

    PropertyInputGroup group = Components.input.propertyGroup().properties(PROPERTIES) //
        .withValueChangeListener(DESCRIPTION, (event, binder) -> { (1)
          binder.refresh(VIRTUAL);
        }) //
        .build();

1 | Add a `PropertyInputValueChangeListener` to the `Input` bound to the `DESCRIPTION` property, and refresh the `VIRTUAL` property `Input` value when the `DESCRIPTION` property value changes

To disable the read-only properties rendering and management, the `excludeReadOnlyProperties()` builder method can be used.

    PropertyInputGroup group = Components.input.propertyGroup().properties(PROPERTIES) //
        .excludeReadOnlyProperties() (1)
        .build();

1 | Exclude any read-only property from `Input` rendering and binding

### 8.8. Input Forms

The PropertyInputForm component represents a PropertyInputGroup which is also a UI `Component`, and thus can be directly used to display and manage the `Input` components in the UI.

It extends the ComposableComponent API, which represents an UI component with a base layout and the capability to compose a set of UI components on this layout.

The Composer API is used to compose the `Input` components on the UI, and must be provided to the `PropertyInputForm` at configuration time, along with the base layout component on which the `Input` components will be organized.

When a `PropertyInputForm` component is obtained using the Components API, a set of methods are available to create a `PropertyInputForm` using one of the standard Vaadin layouts. Using these methods, a default `ComponentContainer` composer is provided, which adds the `Input` components to the base layout in the order they are provided by the `PropertyInputForm` property set.

| The `ComposableComponent` interface provides the `componentContainerComposer()` static method to obtain a default composer which uses a Vaadin `ComponentContainer` as base layout.

    PropertyInputForm form = Components.input.form().properties(PROPERTIES).build(); (1)
    form = Components.input.formVertical().properties(PROPERTIES).build(); (2)
    form = Components.input.formHorizontal().properties(PROPERTIES).build(); (3)
    form = Components.input.formGrid().properties(PROPERTIES).build(); (4)

1 | Create a `PropertyInputForm` using a `FormLayout` as base content layout
2 | Create a `PropertyInputForm` using a `VerticalLayout` as base content layout
3 | Create a `PropertyInputForm` using a `HorizontalLayout` as base content layout
4 | Create a `PropertyInputForm` using a `GridLayout` as base content layout

#### 8.8.1. Base layout initialization

A `initializer(…​)` builder method is available to perform custom configuration of the base layout component of the `PropertyInputForm`.

    PropertyInputForm form = Components.input.formGrid().properties(PROPERTIES) //
        .initializer(gridLayout -> { (1)
          gridLayout.setSpacing(true);
          gridLayout.addStyleName("my-style");
        }).build();

1 | Provide base layout component initialization using an initializer

#### 8.8.2. `Input` components composition

The Composer API is used to compose the `Input` components on the `PropertyInputForm` base layout, and can be provided at configuration time either to provide a custom component composition strategy.

The `Input` components composition using the currently configured `Composer` is triggered by the `compose()` method. By default, the components composition is automatically performed when the `PropertyInputForm` component is a attached to a parent layout.

    PropertyInputForm form = Components.input.form(new FormLayout()) (1)
        .properties(PROPERTIES).composer((layout, source) -> { (2)
          source.getValueComponents().forEach(c -> layout.addComponent(c.getComponent()));
        }).build();

1 | A `FormLayout` instance is provided as base layout component
2 | Configure a `Composer` to compose the `Input` components on the form base layout. The `PropertyComponentSource` type argument can be used to obtain the available `Input` components

To disable this behaviour, the `composeOnAttach(…​)` method of the `PropertyInputForm` builder API can be used.

    PropertyInputForm form = Components.input.form(new FormLayout()).properties(PROPERTIES) //
        .composer((layout, source) -> {
          source.getValueComponents().forEach(c -> layout.addComponent(c.getComponent()));
        }).composeOnAttach(false) (1)
        .build();

    form.compose(); (2)

1 | Disable the automatic `Input` components composition when the `PropertyInputForm` component is a attached to a parent layout
2 | Explicitly use the `compose()` method to perform components composition

#### 8.8.3. `Input` components width mode

When the `Input` components are composed on a `PropertyInputForm` content component, the ComponentsWidthMode enumeration can be used to configure the strategy to use to handle the component widths.

The available strategies are:

- NONE: The width of each `Input` component will not be altered.

- AUTO: The width of each `Input` component will adjusted according to parent layout width: if the parent layout is 100% wide, the components width will be setted to 100%.

- FULL: The width of each `Input` component will always be setted to 100%.

The default strategy is `AUTO`.

The strategy can be changed using the `componentsWidthMode` method of the `PropertyInputForm` builder API.

    PropertyInputForm form = Components.input.form().properties(PROPERTIES)
        .componentsWidthMode(ComponentsWidthMode.FULL) (1)
        .build();

1 | Set the `ComponentsWidthMode` to `FULL`: all the form `Input` components will be 100% wide

#### 8.8.4. `Input` components configuration

The `ComposableComponent` type builders, including the `PropertyInputForm` builder API, allow to provide custom configurator functions in order to configure the `Input` components just after they are rendered.

For each `Property` of the `PropertyInputForm` property set, you can provide a `Consumer` to use as `ComponentConfigurator`, which makes available a complete set of methods to configure the Input `Component` associated to a `Property` before rendering it in UI. For example, you can set the component size, the icon, the description and so on.

    PropertyInputForm form = Components.input.form().properties(PROPERTIES)
        .componentConfigurator(ID, cfg -> cfg.styleName("id-input").description("The ID")) (1)
        .componentConfigurator(DESCRIPTION, cfg -> cfg.icon(VaadinIcons.CLIPBOARD_TEXT)) (2)
        .build();

1 | Configure the `ID` property `Component`
2 | Configure the `DESCRIPTION` property `Component`

### 8.9. View components

The ViewComponent API represents a UI component which can be used to display a value on the user interface. Unlike an `Input` type component, the value cannot be changed by the use.

As a `ValueHolder`, the view component value can be setted and obtained using the `setValue` and `getValue` methods.

Just like an `Input` type component, the actual UI component to display is obtained form the `getComponent()` method.

The Components API can be used to obtain a default `ViewComponent` implementation (backed by a Vaadin `Label` component) for a specific value type, using the `view.component(Class<? extends T> valueType)` method.

    ViewComponent<String> view = Components.view.component(String.class) (1)
        .caption("TheCaption", "caption.message.code") (2)
        .icon(VaadinIcons.CAMERA) //
        .styleName("my-style") //
        .build();

    view.setValue("TestValue"); (3)

    String value = view.getValue(); (4)

1 | Get a `ViewComponent` builder using a `String` value type
2 | Configure the `ViewComponent` component
3 | Set the `ViewComponent` value
4 | Get the `ViewComponent` value

#### 8.9.1. View component Groups and Forms

Just like the `Input` components, a `ViewComponent` set can be organized in groups and handled using forms.

- The PropertyViewGroup API con be used to create `ViewComponent` groups.

- The PropertyViewForm API con be used to create `ViewComponent` form components.

These component containers rely on the Holon Platform the Property model to bind each `ViewComponent` to a `Property` and they use the `PropertyBox` type to provide the property values to show.

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

    final PropertySet<?> PROPERTIES = PropertySet.of(ID, DESCRIPTION);

    PropertyViewGroup viewGroup = Components.view.propertyGroup().properties(PROPERTIES).build(); (1)

    PropertyViewForm viewForm = Components.view.formVertical().properties(PROPERTIES).build(); (2)

    viewForm.setValue(PropertyBox.builder(PROPERTIES).set(ID, 1L).set(DESCRIPTION, "Test").build()); (3)
    PropertyBox value = viewForm.getValue(); (4)

1 | Create a `PropertyViewGroup` using the `PROPERTIES` property set
2 | Create a `PropertyViewForm` using the `PROPERTIES` property set and a `VerticalLayout` as base layout
3 | Set the form value using a `PropertyBox`
4 | Get the form value as a `PropertyBox`

The `PropertyViewGroup` and `PropertyViewForm` provide all the base components configuration capabilities of their corresponding PropertyInputGroup and PropertyInputForm implementations.

So, for example, it is possible to configure a `Composer` to customize the `ViewComponent` components composition strategy for a `PropertyViewForm` or to provide component initializers at configuration time.

    PropertyViewForm viewForm = Components.view.form(new FormLayout()).properties(PROPERTIES) //
        .initializer(layout -> layout.setMargin(true)) (1)
        .composer((layout, source) -> { (2)
          source.getValueComponents().forEach(c -> layout.addComponent(c.getComponent()));
        }) //
        .componentConfigurator(DESCRIPTION, cfg -> cfg.styleName("my-style")) (3)
        .componentsWidthMode(ComponentsWidthMode.FULL) (4)
        .build();

1 | Base layout initializer
2 | Custom component `Composer`
3 | `DESCRIPTION` property `ViewComponent` component configurator
4 | Set the `ComponentsWidthMode` to `FULL`: all the form `ViewComponent` components will be 100% wide

#### 8.9.2. `ViewComponent` captions

When the `PropertyViewForm` builder API makes available some additional methods to directly configure the captions of the `ViewComponent` managed by the form.

For each `Property` of the form property set, the `ViewComponent` caption can be setted using the `propertyCaption` method or hidden using the `hidePropertyCaption` method.

    PropertyViewForm viewForm = Components.view.form(new FormLayout()).properties(PROPERTIES) //
        .propertyCaption(DESCRIPTION, "My caption") (1)
        .hidePropertyCaption(ID) (2)
        .build();

1 | Set the caption for the `ViewComponent` bound to the `DESCRIPTION` property
2 | Hide the caption for the `ViewComponent` bound to the `ID` property

## 9. Item listing

The ItemListing API can be used to display a set of items as tabular data using a `Grid` type UI component and to manage the data items.

Each item property to display is bound to a column, and a property id is used to bind the item property to the listing column.

The `ItemListing` is a Selectable component, supporting items selection in single or multiple mode.

The `ItemListing` API provides a set of methods to control the listing appearance, showing and hiding columns, sorting and refreshing the item set, and so on. See Item listing API and configuration.

Two `ItemListing` implementations are available to use this component:

- PropertyListing: Uses a `PropertyBox` as item type and the listing column ids are the `Property` instances of the provided property set.

- BeanListing: Uses a Java Bean as item type and the listing column ids are the Bean property names.

### 9.1. Item listing properties

An ItemListing component manages the its data as a set of items and each item attribute is identified by a property which also acts as listing column id.

The available item attributes represent the item property set and can be used to access and display the item data in the listing.

Each concrete ItemListing implementation is bound to a specific item type and property type.

Since each property id represents an item listing column id, it is used be the builder API to identify the listing columns and provide a set of column configuration methods. See Item listing API and configuration for details.

#### 9.1.1. Visible properties

By default, all the properties of the listing property set are rendered as listing columns, in the same order they are provided by the property set itself.

The listing columns display can be changed as described below.

1. Explicit column selection and display order:

To explicitly select which properties are to be rendered as listing columns and to declare the columns order, the `ItemListing` builder API provides specialized versions of the `build()` method, which accept an array or an `Iterable` of property ids (whose type will be the concrete type used by the specific `ItemListing` implementation) to declare the visible columns and their order.

For example, when using the PropertyListing implementation, the item’s property ids will be represented using the Property abstraction and the visible item listing columns (and their order) can be configured as in the example below:

    final NumericProperty<Long> ID = NumericProperty.longType("id");
    final StringProperty DESCRIPTION = StringProperty.create("description");
    final BooleanProperty ACTIVE = BooleanProperty.create("active");

    final PropertySet<?> PROPERTIES = PropertySet.of(ID, DESCRIPTION, ACTIVE);

    PropertyListing listing = Components.listing.properties(PROPERTIES) (1)
        .build(DESCRIPTION, ID); (2)

1 | The `PROPERTIES` property set is used as item property set. By default, the displayed column set and ordering would be: `ID`, `DESCRIPTION`, `ACTIVE`.
2 | Change the listing visible columns and their order: the `DESCRIPTION` property first and then the `ID` property

2. Default column display ordering configuration:

The `ItemListing` builder API provides a set of methods to configure the default column display ordering, which is applied only when an explicit ordering is not provided using the specialized `build(…​)` methods as described in the previous section.

The available column position configuration methods are:

- `displayAsFirst(P property)`: Display the column represented by given property id before any other listing column.

- `displayAsLast(P property)`: Display the column represented by given property id after any other listing column.

- `displayBefore(P property, P beforeProperty)`: Display the column represented by given property id before the listing column represented by the `beforeProperty` property id.

- `displayAfter(P property, P afterProperty)`: Display the column represented by given property id after the listing column represented by the `afterProperty` property id.

The property id type (`P`) depends on the concrete `ItemListing` implementation.

    final NumericProperty<Long> ID = NumericProperty.longType("id");
    final StringProperty DESCRIPTION = StringProperty.create("description");
    final BooleanProperty ACTIVE = BooleanProperty.create("active");

    final PropertySet<?> PROPERTIES = PropertySet.of(ID, DESCRIPTION, ACTIVE);

    PropertyListing listing = Components.listing.properties(PROPERTIES) //
        .displayAsFirst(ACTIVE) (1)
        .displayBefore(ID, DESCRIPTION) (2)
        .displayAfter(DESCRIPTION, ACTIVE) (3)
        .build();

1 | Configure the column which corresponds to the `ACTIVE` property id to be displayed as first
2 | Configure the `ID` column to be displayed before the `DESCRIPTION` column
3 | Configure the `DESCRIPTION` column to be displayed after the `ACTIVE` column

### 9.2. PropertyListing

A PropertyListing implementation can be obtained using the Components API, through the `listing.properties` method.

The `Property` set to use to configure the `PropertyListing` must be provided, for each `Property` of the property set a listing column and configured to the `Property` types. Each column will be identified by the `Property` itself.

In particular, for each `Property` of the property set:

- The property caption, if available, will be used as column header. The caption/header localization is fully supported and performed if a `LocalizationContext` is available. See Messages localization support for details.

- The cells of the column which corresponds to a property will be rendered according to the property type and relying on the available property value presenters.

- For any property of `com.vaadin.ui.Component` type, a `ComponentRenderer` will be automatically used to render the Vaadin Component in the listing column cells.

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

    final PropertySet<?> PROPERTIES = PropertySet.of(ID, DESCRIPTION);

    PropertyListing listing = Components.listing.properties(PROPERTIES).build(); (1)

1 | Create a `PropertyListing` using given `PROPERTIES` property set

| See the Item listing API and configuration to learn about the item listing API operations and configuration options.

#### 9.2.1. Items type and identifiers

The PropertyBox type is used to represent a `PropertyListing` item, i.e. a listing row. For each property listing row, the `PropertyBox` type item collects the values of each `Property` bound to the listing columns.

By default, the listing property set identifier properties are used to provide the `PropertyBox` items identifiers, if available. See the property set identifier properties documentation for details.

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

    final PropertySet<?> PROPERTIES = PropertySet.builderOf(ID, DESCRIPTION).withIdentifier(ID).build(); (1)

    PropertyListing listing = Components.listing.properties(PROPERTIES).build();

1 | Set the `ID` property as property set identifier property

#### 9.2.2. Items data source

The `PropertyBox` type item set handled by the `PropertyListing` is provided using an items data source, which can be configured using the `PropertyListing` builder API using the `dataSource` methods.

The ItemDataProvider API is used to represent the items data source.

An `ItemDataProvider` implementation provides methods to obtain the item set size and to load a subset of the items using a limit which represents the subset size and a offset index to specify which subset to return. For a `PropertyListing`, the items subset is returned as a Stream of `PropertyBox` instances.

The `ItemDataProvider` methods accepts a `QueryConfigurationProvider` instance, to provide the `QueryFilter` and the `QuerySort` to be used to query the item set.

| See the Query documentation for information about the query definition using the Holon Platform Property model.

    ItemDataProvider<PropertyBox> dataProvider = ItemDataProvider.create(cfg -> 0, (1)
        (cfg, offset, limit) -> Stream.empty()); (2)

    PropertyListing listing = Components.listing.properties(PROPERTIES) //
        .dataSource(dataProvider) (3)
        .build();

1 | Create a `ItemDataProvider` which always returns a 0 size item set
2 | Return an empty Stream as item set
3 | Create a `PropertyListing` using the `dataProvider` as items data source

A convenience method is available to use the Datastore API as items data source, providing the `DataTarget` to use to perform the query on the concrete persistence source.

    Datastore datastore = getDatastore();

    PropertyListing listing = Components.listing.properties(PROPERTIES) //
        .dataSource(datastore, DataTarget.named("test")) (1)
        .build();

1 | Use a `Datastore` as data source. The `Datastore` API will be used to perform the queries to obtain the items set, with the given `DataTarget` as query target

#### 9.2.3. Item identifier configuration

When the property set of the `PropertyListing`, used to represent the `PropertyBox` type items, does not provide one or more identifier properties as described in the Items type and identifiers section, the ItemIdentifierProvider interface can be used to provide the item identifiers.

    ItemDataProvider<PropertyBox> dataProvider = getDataProvider();

    PropertyListing listing = Components.listing.properties(PROPERTIES) //
        .dataSource(dataProvider, item -> item.getValue(ID)) (1)
        .build();

    listing = Components.listing.properties(PROPERTIES) //
        .dataSource(getDatastore(), DataTarget.named("test"), ID) (2)
        .build();

1 | Create a `PropertyListing` and provide an `ItemDataProvider` as data source, along with an `ItemIdentifierProvider` which provides the value of the `ID` property as item identifier
2 | A shorter builder method to use the `ID` property as item identifier when a `Datastore` is used as items data source

#### 9.2.4. Item query configuration

One or more `QueryConfigurationProvider` can be registered in the `PropertyListing` to provide additional and dynamic items query configuration elements, such as `QueryFilter` and `QuerySort`.

    PropertyListing listing = Components.listing.properties(PROPERTIES) //
        .dataSource(getDatastore(), DataTarget.named("test")) //
        .withQueryConfigurationProvider(new QueryConfigurationProvider() { (1)

          @Override
          public QueryFilter getQueryFilter() {
            return ID.gt(0L);
          }

          @Override
          public QuerySort getQuerySort() {
            return DESCRIPTION.asc();
          }

        }).build();

1 | Add a `QueryConfigurationProvider` to the `PropertyListing`

#### 9.2.5. Using `VirtualProperty` for "generated" columns

The VirtualProperty abstraction can be used to declare generated columns for a `PropertyListing` component, i.e. columns whose contents are not directly bound to an item property value, but are instead generated using a function, for example relying on the item data (represented by a `PropertyBox`) for each listing row (i.e. for each item instance).

Since the `VirtualProperty` provides its value through a `PropertyValueProvider`, the provider function is invoked when the listing column cells are rendered to obtain the column content to display, providing the current item/row value as a `PropertyBox` instance.

The generated column content type will match the `VirtualProperty` type, so if it is not of `String` type a suitable renderer should be configured to consistently display the column contents. See Columns rendering to learn how to configure column renderers and Using `VirtualProperty` for `Component` type columns.

A `VirtualProperty` type column can be added to a `PropertyListing` component in the following ways:

1. Include the `VirtualProperty` in the listing property set:

When one or more `VirtualProperty` type property is included in the default `PropertyListing` property set, a column bound to each `VirtualProperty` is included in the listing by default and no further configuration is required.

In this scenario, the `VirtualProperty` will be part of the item property set and available as item property through the `PropertyBox` item representation.

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

    final VirtualProperty<String> DESCRIPTION = VirtualProperty.create(String.class,
        item -> "ID: " + item.getValue(ID)); (1)

    PropertyListing listing = Components.listing.properties(ID, TEXT) //
        .build(ID, TEXT, DESCRIPTION); (2)

1 | A `String` type `VirtualProperty` which uses the `ID` item property value to provide the generated value
2 | The `DESCRIPTION` virtual property is included in the `PROPERTIES` listing property set, so it will be included and displayed as a column by default

2. Provide a `VirtualProperty` as a visible column:

When a `VirtualProperty` is declared within the visible columns list through the appropriate `build(…​)` methods, it will be automatically configured as listing column even if it is not part of the item listing property set.

    final NumericProperty<Long> ID = NumericProperty.longType("id");
    final VirtualProperty<String> DESCRIPTION = VirtualProperty.create(String.class,
        item -> "ID: " + item.getValue(ID)); (1)

    final PropertySet<?> PROPERTIES = PropertySet.of(ID, DESCRIPTION);

    PropertyListing listing = Components.listing.properties(PROPERTIES).build(); (2)

1 | A `String` type `VirtualProperty` which uses the `ID` item property value to provide the generated value
2 | The `DESCRIPTION` virtual property is included in the visible properties list, so it will be automatically included and displayed as a column

3. Use the `withVirtualProperty(…​)` builder API methods:

The `PropertyListing` builder API provide a set of convenience methods to add and configure a generated column using a `VirtualProperty`.

The `withVirtualProperty(…​)` methods accept the property type and the property value provider function (or an explicit `VirtualProperty` reference) and provide a specific builder API to configure the column which corresponds to the virtual property before adding it to the listing through the `add()` method.

    PropertyListing listing = Components.listing.properties(PROPERTIES) //
        .withVirtualProperty(String.class, item -> "ID: " + item.getValue(ID)).add() (1)
        .withVirtualProperty(item -> "ID: " + item.getValue(ID)).add() (2)
        .build();

1 | Add a `String` type virtual property providing the property value provider function and using `add()` to include the generated column in the listing
2 | For `String` type virtual properties, a convenience shorter method is available

The virtual property column builder API provides a set of configuration methods to configure the column header, the width, the visibility, the style generator, the column renderer and the sorting behaviour:

    PropertyListing listing = Components.listing.properties(PROPERTIES) //
        .withVirtualProperty(String.class, item -> "ID: " + item.getValue(ID)) (1)
        .header("The header") (2)
        .headerHTML("The <strong>header</strong>") (3)
        .alignment(ColumnAlignment.CENTER) (4)
        .width(100) (5)
        .minWidth(50) (6)
        .maxWidth(200) (7)
        .expandRatio(1) (8)
        .resizable(true) (9)
        .hidable(true) (10)
        .hidden(false) (11)
        .hidingToggleCaption("Show/hide") (12)
        .style("my-style") (13)
        .style((property, item) -> "stylename") (14)
        .render(new HtmlRenderer()) (15)
        .sortUsing(ID) (16)
        .sortGenerator((property, asc) -> QuerySort.of(ID, asc)) (17)
        .add() (18)
        .build();

1 | Declare a `String` type virtual property providing the property value provider function
2 | Configure the column header
3 | Configure the column header as HTML
4 | Configure the column alignment
5 | Configure the column width
6 | Configure the column minimum width
7 | Configure the column maximum width
8 | Configure the column expand ratio
9 | Set the column as resizable
10 | Set the column as hidable
11 | Set the column as not hidden
12 | Configure the column hiding toggle caption
13 | Provide a fixed column CSS style class name
14 | Provide the column CSS style class provider
15 | Set the column renderer
16 | Declare to use the `ID` property to implement the column sorting behaviour
17 | Provide a column sorting generator
18 | Add the virtual property column to the listing

By default, the column added using the `withVirtualProperty(…​)` methods are appended at the end of the listing columns. To control the virtual property column positioning within the listing columns, the following builder API methods can be used:

- `displayAsFirst()`: Display the virtual property column before any other listing column.

- `displayAsLast()`: Display the virtual property column after any other listing column.

- `displayBefore(Property property)`: Display the virtual property column before the listing column represented by the `property` property id.

- `displayAfter(Property property)`: Display the virtual property column after the listing column represented by the `property` property id.

    PropertyListing listing = Components.listing.properties(PROPERTIES) //
        .withVirtualProperty(String.class, item -> "ID: " + item.getValue(ID)) (1)
        .displayAsFirst() (2)
        .displayAsLast() (3)
        .displayBefore(DESCRIPTION) (4)
        .displayAfter(ID) (5)
        .add().build();

1 | Declare a `String` type virtual property providing the property value provider function
2 | Display the virtual property column before any other listing column
3 | Display the virtual property column after any other listing column
4 | Display the virtual property column before the listing column bound the `DESCRIPTION` property
5 | Display the virtual property column after the listing column bound the `ID` property

When a virtual property column has to be positioned relative to another virtual property column, you need a property id to which to refer. For this reason, specialized `withVirtualProperty(…​)` methods which accept the virtual property name are available.

Furthermore, the `displayBeforeColumnId(String columnId)` and `displayAfterColumnId(String columnId)` builder API methods can be use to display a virtual property column before or after another virtual property column with an assigned name.

    PropertyListing listing = Components.listing.properties(PROPERTIES) //
        .withVirtualProperty(String.class, "_myid", item -> "ID: " + item.getValue(ID)).displayAfter(ID).add() (1)
        .withVirtualProperty(String.class, item -> "ID2: " + item.getValue(ID)).displayBeforeColumnId("_myid") (2)
        .add().build();

1 | Declare a `String` type virtual property providing the property value provider function and `_myid` as virtual property name
2 | Declare another virtual property column and display it before the `_myid` virtual property

#### 9.2.6. Using `VirtualProperty` for `Component` type columns

When a `Property` of the `PropertyListing` property set is declared as `com.vaadin.ui.Component` type, the listing configures by default a suitable renderer to display the property value as a Vaadin Component, instead of a `String`.

When a listing `Component` type column has to be dinamically generated when the listing is rendered, the VirtualProperty property type can be used.

Since the `VirtualProperty` provides its value through a `PropertyValueProvider`, the provider is invoked when the listing column cells are rendered to obtain the `Component` to display, providing the current row values as `PropertyBox`, which can be used for component generation.

The `VirtualProperty` can be declared in the listing property set as any other Property, but when it is only used for a specific item listing column to render a `Component` it can be only declared as visible column, in the `build(…​)` method. This way, it will not be part of the listing property set (and it will not be included in the row `PropertyBox` properties) and will only be used as generated column.

    final VirtualProperty<Component> EDIT = VirtualProperty.create(Component.class).message("Edit") (1)
        .valueProvider( (2)
            row -> Components.button().styleName(ValoTheme.BUTTON_ICON_ONLY).icon(VaadinIcons.EDIT)
                .onClick(e -> {
                  Long rowId = row.getValue(ID); (3)
                  // perform edit action ...
                }).build());

    PropertyListing listing = Components.listing.properties(PROPERTIES) (4)
        .build(EDIT, ID, DESCRIPTION); (5)

    listing = Components.listing.properties(PROPERTIES) //
        .build(PropertySet.builder().add(PROPERTIES).add(EDIT).build()); (6)

1 | Declare a `VirtualProperty` of `Component` type. The configured message will be used as column header.
2 | The property value provider returs a `Button` component
3 | Since the row `PropertyBox` is provided at column cell generation time, we can use it to obtain a property value for the current row. In this example, the `ID` property value is obtained.
4 | The listing property set do not includes the `EDIT` virtual property
5 | The `EDIT` virtual property is declared as visible column, in the first position in this case
6 | Another example in which the visible columns property set is composed joining the `PROPERTIES` set and the `EDIT` virtual property

### 9.3. BeanListing

A BeanListing implementation can be obtained using the Components API, through the `listing.items` method.

The Bean class to use as items type must be provided as construction time.

The Holon Platform Bean introspection API is used to detect the Bean class properties to use as listing columns and the Bean property names are used as column ids.

All the suitable bean property configuration attributes supported by the Holon Platform Bean introspection API are used to automatically configure the listing component, for example to set the column headers using the localizable property captions.

See the Bean property configuration section to learn about the Bean introspection API configuration capabilities and the available builtin annotations which can be used to provide a set of configuration attributes, such as `@Caption` or `@Sequence`.

For example, given the following bean class:

    private class TestData {

      private Long id;
      private String description;

      // getters and setters omitted

A `BeanListing` which uses the bean class can be obtained as follows:

    BeanListing<TestData> listing = Components.listing.items(TestData.class) (1)
        .build();

1 | Create a `BeanListing` using `TestData` as items data type

| See the Item listing API and configuration to learn about the item listing API operations and configuration options.

#### 9.3.1. Bean items data source

The data source to provide the bean items for a `BeanListing` can be configured using the `dataSource` builder API methods.

1. Using an `ItemDataProvider` as items data source:

The ItemDataProvider API can be used as items data source.

For example, given a `List` of `TestData` bean instances, an in-memory `ItemDataProvider` can be configured in the following way:

    final List<TestData> data = Arrays.asList(new TestData(1, "One"), new TestData(2, "Two"),
        new TestData(3, "Three"));

    BeanListing<TestData> listing = Components.listing.items(TestData.class) //
        .dataSource(ItemDataProvider.create(cfg -> data.size(), (1)
            (cfg, offset, limit) -> data.stream().skip(offset).limit(limit)))
        .build();

1 | Set an `ItemDataProvider` which uses the `data` List as items data source

2. Using a `Datastore` as items data source:

A Datastore implementation can be used as items data source to obtain the bean items from a persistence source.

The properties which will be used to perform query operations using the `Datastore` API will be the Bean properties obtained as a BeanPropertySet using the Holon Platform Bean introspection API.

    final Datastore datastore = getDatastore();

    BeanListing<TestData> listing = Components.listing.items(TestData.class) //
        .dataSource(datastore, DataTarget.named("test")) (1)
        .build();

1 | Use a `Datastore` and given `DataTarget` as items data source

The `BeanListing` API makes available a `refresh()` method to refresh the current items set, causing items reloading from the items data source.

    BeanListing<TestData> listing = Components.listing.items(TestData.class) //
        .dataSource(getDatastore(), DataTarget.named("test")).build();

    listing.refresh(); (1)

1 | Refresh the items set

#### 9.3.2. Dynamically generated columns

The `BeanListing` component supports virtual columns definition to declare generated column types, which contents are generated when the listing is rendered, for example to provide `Component` type column contents.

The `withVirtualColumn(String id, Class<V> type, ValueProvider<T, V> valueProvider)` method of the `BeanListing` builder API allows to declare a virtual column, providing:

- The virtual column id and type

- A `ValueProvider` which will be used to generate the column cells, using the row item bean instance

The declared virtual column id can later be used to include the virtual column in the visible column in the required position.

    BeanListing<TestData> listing = Components.listing.items(TestData.class)
        .withVirtualColumn("delete", Button.class, bean -> { (1)
          return Components.button().icon(VaadinIcons.TRASH).onClick(e -> {
            Long rowId = bean.getId(); (2)
          }).build();
        }).build("delete", "id", "description"); (3)

1 | Declare a virtual column of `Button` type and `delete` as column id
2 | The bean instance of the current row can be used to obtain row values, for example the id attribute in this case
3 | Declare the `delete` column as visible and render it as first column

### 9.4. Item listing API and configuration

The item listing component builder API provides a wide set of configuration methods which can be used to:

- Configure the listing columns, header and footer sections.

- Register a number of listeners for different event types.

- Configure the items data source query.

See the next sections for details.

#### 9.4.1. Columns configuration

The listing component columns can be configured in a number of ways. Below is provided an example which uses a `PropertyListing` and shows the available column configuration methods:

    PropertyListing listing = Components.listing.properties(PROPERTIES) //
        .header(ID, "Custom ID header") (1)
        .header(ID, "Default header", "id-header-message-code") (2)
        .headerHTML(ID, "HTML <strong>header</strong>") (3)
        .columnHidingAllowed(true) (4)
        .hidable(ID, false) (5)
        .columnReorderingAllowed(true) (6)
        .alignment(ID, ColumnAlignment.RIGHT) (7)
        .hidden(DESCRIPTION, true) (8)
        .resizable(ID, false) (9)
        .width(ID, 100) (10)
        .expandRatio(DESCRIPTION, 1) (11)
        .minWidth(DESCRIPTION, 200) (12)
        .maxWidth(DESCRIPTION, 300) (13)
        .minimumWidthFromContent(DESCRIPTION, true) (14)
        .style(ID, (property, item) -> item.getValue(DESCRIPTION) != null ? "empty" : "not-empty") (15)
        .withPropertyReorderListener((properties, userOriginated) -> { (16)
          // ...
        }).withPropertyResizeListener((property, widthInPixel, userOriginated) -> { (17)
          // ...
        }).withPropertyVisibilityListener((property, hidden, userOriginated) -> { (18)
          // ...
        }).build();

1 | Set a custom header caption for the `ID` property/column
2 | Set the `ID` property/column localizable header caption providing the default message and the localization message code (See the Internationalization documentation for further information about localization)
3 | Set a the header caption for the `ID` property/column using HTML markup
4 | Set whether the listing columns can be hidden
5 | Set that the `ID` property/column cannot be hidden
6 | Set whether the listing columns can reordered
7 | Set the `ID` property/column cell contents alignment
8 | Set the `DESCRIPTION` property/column as hidden by default
9 | Set the `ID` property/column as not resizable
10 | Set the `ID` property/column width in pixels
11 | Set the `DESCRIPTION` property/column expand ratio
12 | Set the `DESCRIPTION` property/column minimum width
13 | Set the `DESCRIPTION` property/column maximum width
14 | Set to use the width of the contents in the column as `DESCRIPTION` property/column width
15 | Set the `ID` property/column CSS style generator
16 | Add a listener to be notified when the listing columns order changes
17 | Add a listener to be notified when a property/column is resized
18 | Add a listener to be notified when a property/column is shown or hidden

#### 9.4.2. Columns rendering

By default, the cells of a column bound to a `Property` are rendered using the Holon Platform presenters available from the default registry, to provide the `String` representation of the cell value.

| See the String value presenters documentation for details.

The default column rendering can be overridden using a custom Vaadin `Renderer`. The provided `Renderer` must handle the same data type of the property/column for which it is configured.

Furthermore, a property/column value can be converted to a different value type, and, in this case, a suitable `Renderer` for the converted type must be provided.

    PropertyListing listing = Components.listing.properties(PROPERTIES) //
        .render(ID, new NumberRenderer(Locale.US)) (1)
        .render(ID, value -> String.valueOf(value), new TextRenderer()) (2)
        .build();

1 | Set a custom `NumberRenderer` for the `ID` property/column (which is of type `Long`)
2 | Set a converter to convert the `Long` type value of the `ID` property/column into a `String` and a suitable render according to the new value type

#### 9.4.3. Item listing configuration

The item listing component is highly configurable. Through the builders you can configure:

- The header appeareance, adding and removing header rows and joining header columns

- Showing and configuring a footer section

- Set a number of column as frozen

- Provide rows CSS style using a style generator

- Provide item description (tooltip) for item rows

- Provide a item click listener to listen for user clicks on item rows

- Provide a row details component which can be shown for each item row

    PropertyListing listing = Components.listing.properties(PROPERTIES) //
        .heightByContents() (1)
        .frozenColumns(1) (2)
        .hideHeaders() (3)
        .withRowStyle(item -> { (4)
          return item.getValue(DESCRIPTION) != null ? "has-des" : "no-nes";
        }) //
        .itemDescriptionGenerator(item -> item.getValue(DESCRIPTION)) (5)
        .detailsGenerator(item -> { (6)
          VerticalLayout component = new VerticalLayout();
          // ...
          return component;
        }).withItemClickListener((item, property, index, event) -> { (7)
          // ...
        }).header(header -> { (8)
          header.getDefaultRow().setStyleName("my-header");
        }).footer(footer -> { (9)
          footer.appendRow().setStyleName("my-footer");
        }).footerGenerator((source, footer) -> { (10)
          footer.getRowAt(0).getCell(ID).setText("ID footer");
        }).withPostProcessor(grid -> { (11)
          // ...
        }).build();

1 | Set the height of the listing defined by its contents
2 | Set the frozen columns count
3 | Hide all the listing headers
4 | Set the row CSS style generator
5 | Set the item/row description (tooltip) generator
6 | Set the item/row details component generator
7 | Register a item click listener
8 | Add a style class name to the default header row
9 | Append a row to the listing footer and set a style class name for it
10 | Set the footer generator to invoke to update the listing footer contents
11 | Set a post-processor to customize the internal `Grid` component

#### 9.4.4. Items selection

The item listing component supports items selection, both in single and multiple mode. The listing can be made selectable by using the `setSelectionMode` method or the `selectionMode` builder method.

Just like any other `Selectable` component, the item listing component provides methods to inspect the current selected item/s and change the current selection.

Single selection mode

    PropertyListing listing = Components.listing.properties(PROPERTIES) //
        .selectionMode(SelectionMode.SINGLE) (1)
        .build();

    final PropertyBox ITEM = PropertyBox.builder(PROPERTIES).set(ID, 1L).build();

    PropertyBox selected = listing.getFirstSelectedItem().orElse(null); (2)

    boolean isSelected = listing.isSelected(ITEM); (3)

    listing.select(ITEM); (4)

    listing.deselectAll(); (5)

1 | Set the listing selectable in `SINGLE` selection mode
2 | Get the currently selected item, if any
3 | Check whether the given item is selected
4 | Select the given item
5 | Deselect all (clear current selection)

Multiple selection mode

    PropertyListing listing = Components.listing.properties(PROPERTIES) //
        .build();

    listing.setSelectionMode(SelectionMode.MULTI); (1)

    final PropertyBox ITEM = PropertyBox.builder(PROPERTIES).set(ID, 1L).build();

    Set<PropertyBox> selected = listing.getSelectedItems(); (2)

    boolean isSelected = listing.isSelected(ITEM); (3)

    listing.select(ITEM); (4)

    listing.deselectAll(); (5)

    listing.selectAll(); (6)

1 | Set the listing selectable in `MULTI` selection mode
2 | Get the selected items
3 | Check whether the given item is selected
4 | Select the given item
5 | Deselect all items
6 | Select all items

| The select all checkbox shown in the top left corner of the listing is visible by default. You can control the checkbox visibility using the `selectAllCheckBoxVisibility(…​)` method of the item listing builder.

#### 9.4.5. Items query configuration

The item listing builder provides a number of methods to control the data source items query, allowing to:

- Set a property/column as sortable or not and override the default sort behaviour, for example using another property as query sort target or providing a custom `QuerySort`;

- Set a fixed sort, which will be always appended to current query sorts

- Set a default sort, to be used when no other query sort is configured

- Set a fixed filter, which will be always applied to the query

- Register one or more `QueryConfigurationProvider` to provide custom query configuration logic

    PropertyListing listing = Components.listing.properties(PROPERTIES) //
        .sortable(ID, true) (1)
        .sortUsing(ID, DESCRIPTION) (2)
        .sortGenerator(ID, (property, ascending) -> { (3)
          return ascending ? ID.asc() : ID.desc();
        }) //
        .fixedSort(ID.asc()) (4)
        .defaultSort(DESCRIPTION.asc()) (5)
        .fixedFilter(ID.gt(0L)) (6)
        .withQueryConfigurationProvider(() -> DESCRIPTION.isNotNull()) (7)
        .build();

1 | Set the `ID` property/column as sortable
2 | Set to use the `DESCRIPTION` property to sort the `ID` property/column
3 | Set a custom `QuerySort` for the `ID` property/column
4 | Set a fixed `QuerySort`, which will always to appended to current query sorts
5 | Set the default `QuerySort`, to be used when no other query sort is configured
6 | Set a fixed `QueryFilter`
7 | Add a `QueryConfigurationProvider`

#### 9.4.6. Item set management

The item set component provides methods to manage the item set which is provided as the listing data source, to add, update and remove one or more items in the set.

To reflect the item set management operations in the underlyng data source (for example, a RDBMS), the `CommitHandler` interface is used. The `commit(…​)` method of that interface is invoked at each item set modification, providing the added, updated and removed items. The `CommitHandler` implementation should persist the item set modifications in the concrete data source.

| When using the `dataSource(…​)` builder method which accepts a `Datastore` as data source, a default `CommitHandler` is automatically configured, using the provided `Datastore` to perform the item persistence operations.

    Datastore datastore = getDatastore();

    PropertyListing listing = Components.listing.properties(PROPERTIES) //
        .dataSource(datastore, DataTarget.named("test"), ID) (1)
        .commitHandler((addedItems, modifiedItems, removedItems) -> { (2)
          // ...
        }).build();

    final PropertyBox ITEM = PropertyBox.builder(PROPERTIES).set(ID, 777L).set(DESCRIPTION, "A description")
        .build();

    listing.addItem(ITEM); (3)

    listing.refreshItem(ITEM); (4)

    listing.removeItem(ITEM); (5)

1 | When using the `Datastore` method of the data source builder, a default `CommitHandler` is automatically configured
2 | You can provide a custom `CommitHandler` using the `commitHandler(…​)` builder method
3 | Add an item
4 | Refresh (update) the item
5 | Remove the item

#### 9.4.7. Buffered mode

The item set component supports a buffered mode to handle its items set. When in buffered mode, the item set modifications are cached internally and not reflected to the concrete data source until the `commit()` method is called.

A `discard()` method is provided to discards all changes since last commit.

The same `CommitHandler` as before is used to persist the item set modifications, but it is invoked only when the `commit()` method is called.

    Datastore datastore = getDatastore();

    PropertyListing listing = Components.listing.properties(PROPERTIES) //
        .dataSource(datastore, DataTarget.named("test"), ID) //
        .buffered(true) (1)
        .build();

    final PropertyBox ITEM = PropertyBox.builder(PROPERTIES).set(ID, 777L).set(DESCRIPTION, "A description")
        .build();

    listing.addItem(ITEM); (2)
    listing.refreshItem(ITEM); (3)
    listing.removeItem(ITEM); (4)

    listing.commit(); (5)
    listing.discard(); (6)

1 | Set the listing in buffered mode
2 | Add an item
3 | Refresh (update) the item
4 | Remove the item
5 | commit the item set modifications
6 | discard the item set modifications since the last commit

#### 9.4.8. Editing items

The item listing component supports line-based editing, where double-clicking a row opens the row editor, using the default Vaadin `Grid` editor. The item listing editor must be enabled using the `editable(true)` method of the builder in order to activate the row editor at double-click.

The editor fields to use for each listing property/column will be auto-generated according to the property/column type. This behaviour can be overridden providing custom editor fields for one or more of the listing properties.

The item listing component editor supports validation, allowing to register value validators both for the single property/column fields and for the overall value validation.

    PropertyListing listing = Components.listing.properties(PROPERTIES) //
        .editable(true) (1)
        .editorBuffered(true) (2)
        .editorSaveCaption("Save item") (3)
        .editorCancelCaption("Discard") (4)
        .editable(ID, false) (5)
        .editor(DESCRIPTION, new TextField()) (6)
        .withValidator(Validator.create(pb -> pb.getValue(DESCRIPTION) != null, "Description must be not null")) (7)
        .withValidator(DESCRIPTION, Validator.max(100)) (8)
        .required(ID) (9)
        .build();

1 | Set the listing as editable
2 | Set the row editor in buffered mode
3 | Set the editor save button caption
4 | Set the editor cancel button caption
5 | Set a property as not editable
6 | Set a custom editor field
7 | Add an overall value validator
8 | Add a property value validator
9 | Set the `ID` property as required, automatically adding a not empty validator

## 10. Dialogs

The Holon Vaadin module provides builders to create and show dialog windows.

A dialog window in represented by the Dialog interface, which makes available methods to set the dialog as modal, open and close the dialog window and registere a `CloseListener` to be invoked when the dialog is closed.

    Dialog dialog = Components.dialog() (1)
        .draggable(false) (2)
        .closable(true) (3)
        .resizable(true) (4)
        .modal(true) (5)
        .message("Dialog message", "dialog.message.code") (6)
        .okButtonConfigurator(cfg -> cfg.caption("Done").icon(VaadinIcons.CHECK_CIRCLE_O)) (7)
        .withCloseListener((window, action) -> { (8)
          // ...
        }).build();

    dialog.open(); (9)

    dialog.close(); (10)

1 | Dialog builder
2 | Set as not draggable
3 | Set as closable
4 | Set as resizable
5 | Set as modal
6 | Set the localizable dialog message
7 | Configure the dialog OK button
8 | Add a close listener
9 | Open (show) the dialog
10 | Close (hide) the dialog

### 10.1. Question dialogs

A question dialog is a `Dialog` with a message and two buttons (instead of one) to answer yes or no to a question.

A `QuestionCallback` can be used when the user selects one of the two buttons and the dialog is closed. The callback notifies the selected answer.

    Components.questionDialog() (1)
        .message("Can I do it for you?") (2)
        .yesButtonConfigurator(cfg -> cfg.caption("Ok, let's do it")) (3)
        .noButtonConfigurator(cfg -> cfg.caption("No, thanks")) (4)
        .callback(answeredYes -> { (5)
          Notification.show("Ok selected: " + answeredYes);
        }).build().open(); (6)

1 | Question dialog builder
2 | Set the dialog message (the question)
3 | Change the yes button caption
4 | Change the no button caption
5 | Set the answer callback
6 | Build and open the dialog

## 11. Property renderers and presenters

The Vaadin module takes advantage of the platform foundation property model to provide the most suitable UI components and display values when a `Property` is used.

When a `Property` must be rendered in UI, the components made available by the Vaadin module try to use a suitable `PropertyRenderer`, if available.

By default, the following renderers are automatically registered by the module:

- A Input property renderer

- A Field property renderer, which represents a `HasValue` Vaadin `Component`

- A ViewComponent property renderer

The `Input` and `Field` property renderers generate a UI component to edit a property value, relying on the property type.

The following types are supported:

- String: renders the property as a `TextField`

- Boolean: renders the property as a `CheckBox`

- Enum: renders the property as a `ComboBox`

- LocalDate and LocalDateTime: renders the property as a `DateField` or a `DateTimeField`

- java.util.Date: renders the property as a `DateField` or a `DateTimeField`

- Number: renders the property as a `TextField` which only accepts numbers and decimal/group separators

    final PathProperty<String> TEXT = PathProperty.create("text", String.class);
    final PathProperty<Long> LONG = PathProperty.create("long", Long.class);

    Input<String> input = TEXT.render(Input.class); (1)

    Field<Long> field = LONG.render(Field.class); (2)

    ViewComponent<String> view = TEXT.render(ViewComponent.class); (3)

1 | Render the property as `String` type `Input`
2 | Render the property as `Long` type `Field` (`HasValue` component)
3 | Render the property as `String` type `ViewComponent`

### 11.1. Property localization

When a `LocalizationContext` is available as a context resource, it is used to localize any element to display which supports localization.

| See the LocalizationContext documentation for details about the `LocalizationContext` API and the Context resources documentation for information about the Holon Platform Context architecture.

Concerning to a `Property` related UI component, the `LocalizationContext` is used to:

- Localize the property caption, for example when it is used as a listing column header or as a input field caption

- Obtain the date and time format to use to display a property value or to edit the property value through an input field

- Obtain the number format to be used to display a property value or to edit the property value through an input field

- Obtain the default boolean localized text for the `true` and `false` values

| See the Internationalization documentation for further information about localization.

### 11.2. Custom property renderers

Relying on the standard property renderers features, custom renderers can be registered to:

- Customize the rendered UI component under certain conditions for the default provided rendering types (`Input`, `Field` and `ViewComponent`)

- Provide the rendering for a custom type

For example, to render a specific `String` type property as text area, instead of the default text field, an appropriate renderer can be registered and bound to a suitable property condition:

    final PathProperty<String> TEXT = PathProperty.create("text", String.class);

    InputPropertyRenderer<String> textAreaInputRenderer = p -> Components.input.string(true).build(); (1)

    PropertyRendererRegistry.get().register(p -> p == TEXT, textAreaInputRenderer); (2)

    Input<String> input = TEXT.render(Input.class); (3)

1 | Create a `Input` property renderer which renders the property as a text area
2 | Register the renderer and bind it to a condition which checks the property is exactly the `TEXT` property
3 | From now on, rendering the `TEXT` property as an `Input` field will generate a text area input component

## 12. Vaadin session scope

A Vaadin session platform scope is automatically registered by the Holon Vaadin module.

This `ContextScope` is bound to the current `VaadinSession`, looking up context resources using Vaadin Session attributes.

The scope uses `VaadinSession.getCurrent()` to obtain the current Vaadin session, so this scope is active only when invoked within a Vaadin server request thread.

| See the Context documentation for further information about context scopes and resources.

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

    LocalizationContext.getCurrent().ifPresent(localizationContext -> { (2)
      // LocalizationContext obtained from current Vaadin session
    });

1 | Create a `LocalizationContext` and set it in Vaadin session using the default context key as attribute name
2 | Get the current `LocalizationContext` context resource, which will be obtained form the Vaadin session, if available

## 13. Device information

The Holon platform Vaadin module makes available the DeviceInfo interface, to obtain informations about the device in which the application is running.

The `DeviceInfo` object provides informations about the user agent and screen dimensions, and can be obtained by using a `VaadinRequest` or relying on the currently available `VaadinSession`.

    DeviceInfo.get().ifPresent(info -> {

      info.getScreenWidth();
      info.getScreenHeight();
      info.getViewPortWidth();
      info.getViewPortHeight();
      info.isMobile();
      info.isTablet();
      info.isSmartphone();
      info.isAndroid();
      info.isIPhone();
      // ...

    });

## 14. Navigator

Maven coordinates:

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

The `holon-vaadin-navigator` artifact makes available an extension of the default Vaadin view navigator, represented by the ViewNavigator API.

The `ViewNavigator` API, compared to the standard Vaadin Navigator one, provides additional features and configuration capabilities:

- `View` navigation history tracking, allowing to navigate back to the previous view.

- `View` parameters management, allowing to obtain the parameters values by injection in a `View` instance.

- Easy `View` lifecycle management, supporting `@OnShow` and `@OnLeave` annotated methods to be notified when the view is loaded and unloaded in the UI.

- Default view support, acting as the application’s "home page".

- The possibility to show a view in a `Window`, instead of using the default view display component.

- Support for Context resources injection in `View` instances.

### 14.1. View parameters injection

The navigation parameters can be injected in the `View` class fields using the ViewParameter annotation.

The parameter name for which the value has to be injected in an annotated field is assumed to be equal to the field name. Otherwise, it can be specified using the annotation `value()` property.

When a named parameter value is not available (not provided by the current navigation state), the parameter field will be setted to `null` or the default value for primitive types (for example `0` for `int`, `long`, `float` and `double` types, false for `boolean` types).

The supported parameter value types are:

- `String`

- `Number` (including primitive types)

- `Boolean` (including primitive type)

- `Enum`

- `Date`

- `LocalDate`

- `LocalTime`

- `LocalDateTime`

A view parameter can be declared as required using the `required()` annotation property. A navigation error will be thrown if a required parameter value is missing.

Furthermore, a default value can be provided for a parameter, using the `defaultValue()` annotation property. See the ViewParameter javadocs for information about the default value representation.

    class ViewExample implements View {

      @ViewParameter("myparam") (1)
      private String stringParam;

      @ViewParameter(defaultValue = "1") (2)
      private Integer intParam;

      @ViewParameter(required = true) (3)
      private LocalDate requiredParam;

    }

1 | View parameter injection using the `myparam` parameter name
2 | View parameter with a default value. The parameter name will be the `intParam` field name
3 | A required view parameter declaration

### 14.2. View lifecycle management

In addition to the standard `enter(…​)` method of the `View` interface, two annotations can be used to intercept `View` lifecycle events using `public` View methods:

- OnShow, called by the view navigator right before the view is shown (i.e. rendered in target display component)

- OnLeave, called by the view navigator when the view is about to be deactivated (i.e. a navigation to another view was triggered)

If more than one `OnShow` or `OnLeave` annotated method is present in the `View` class or in its class hierarchy, all these methods will be called and the following behaviour will be adopted:

- Methods will be called following the class hierarchy, starting from the top (the first superclass after `Object`)

- For methods of the same class, no calling order is guaranteed

The `@OnShow` and `@OnLeave` annotated method supports an optional parameter, which can be either of the standard `com.vaadin.navigator.ViewChangeEvent` type or of the extended `ViewNavigatorChangeEvent` type, to obtain informations about the current view navigator, the previous or next `View`, the `View` name and parameters and the optional `Window` in which the View is displayed.

The `OnShow` annotation provides an additional `onRefresh()` property which, if setted to `true`, instruct the navigator to invoke the `OnShow` annotated method also at browser page refresh.

    class ViewExample2 implements View {

      @ViewParameter
      private String myparam;

      @OnShow
      public void onShow() { (1)
        // ...
      }

      @OnShow(onRefresh = true) (2)
      public void onShowAtRefreshToo() {
        // ...
      }

      @OnShow
      public void onShow2(ViewChangeEvent event) { (3)
        String name = event.getViewName(); (4)
        View oldView = event.getOldView(); (5)
        // ...
      }

      @OnShow
      public void onShow3(ViewNavigatorChangeEvent event) { (6)
        ViewNavigator navigator = event.getViewNavigator(); (7)
        Optional<Window> viewWindow = event.getWindow(); (8)
        // ...
      }

      @OnLeave
      public void onLeave() { (9)
        // ...
      }

      @OnLeave
      public void onLeave2(ViewNavigatorChangeEvent event) { (10)
        View nextView = event.getNewView(); (11)
        // ...
      }

    }

1 | Basic `OnShow` annotated method, invoked right before the view is shown
2 | `OnShow` method with `onRefresh()` setted to `true`: this method will be invoked also at browser page refresh
3 | `OnShow` method with a default `ViewChangeEvent` parameter
4 | Get the View name
5 | Get the previous View
6 | `OnShow` method with a `ViewNavigatorChangeEvent` parameter
7 | Get the `ViewNavigator`
8 | Get the `Window` in which the view is displayed if it was requested to open the View in a window
9 | Basic `onLeave` annotated method
10 | `onLeave` method with a `ViewNavigatorChangeEvent` parameter
11 | Get the View being activated

### 14.3. Providing the View contents

By default, the `View` is rendered as the UI component which is represented by the `View` class.

You can override the standard Vaadin 8 `getViewComponent()` method of the `View` class to control which `Component` to provide as `View` content.

    class ViewExampleContent extends VerticalLayout implements View { (1)

      public ViewExampleContent() {
        super();
        addComponent(new Label("View content"));
      }

    }

    class ViewExampleContentProvider implements View {

      @Override
      public Component getViewComponent() { (2)
        boolean mobile = DeviceInfo.get().map(info -> info.isMobile()).orElse(false);
        return mobile ? buildMobileViewContent() : buildDefaultViewContent();
      }

    }

1 | Default `View` implementation extending a `Component` class (a `VerticalLayout`). The displayed `View` content will be the component itself
2 | Provide the `View` content using the `getViewComponent()` method. In this example, a different UI component is provided according to the device type, checking if the user is running the application in a mobile device

### 14.4. ViewNavigator Configuration

Just like the standard Vaadin navigator, the `ViewNavigator` implementation requires two elements which must be configured in order to work properly:

- A `ViewProvider` to provide the `View` instances by view name

- A `View` display component to show the view contents in the UI, which can be a `ComponentContainer` (replacing the contents of the container with the active `View` content), a `SingleComponentContainer` (using the `setContent(…​)` method to set the active `View` content) or a `ViewDisplay` object to implement a custom `View` display logic.

In addition to the required configuration elements, the `ViewNavigator` supports:

- Setting a default view name, which will be used as target of the `ViewNavigator.navigateToDefault()` method and as a fallback by the `ViewNavigator.navigateBack()` method if no other `View` is available in navigation history

- Setting a error view or a error `ViewProvider` to provide the `View` to be displayed when no other `View` matches a navigation state

- Setting the max navigation history size

- Register a `ViewChangeListener` for listening to `View` changes before and after they occur

The `builder()` method of the `ViewNavigator` interface provides a fluent builder to configure a navigator and bind it to a Vaadin `UI`.

    class AppUI extends UI {

      @Override
      protected void init(VaadinRequest request) {
        ViewNavigator navigator = ViewNavigator.builder() (1)
            .viewDisplay(this) (2)
            .addProvider(getViewProvider()) (3)
            .defaultViewName("home") (4)
            .errorView(MY_ERROR_VIEW) (5)
            .errorViewProvider(getErrorViewProvider()) (6)
            .maxNavigationHistorySize(1000) (7)
            .navigateToDefaultViewWhenViewNotAvailable(true) (8)
            .withViewChangeListener(e -> { (9)
              // ...
              return true;
            }).buildAndBind(this); (10)
      }

    }

1 | Obtain the `ViewNavigator` builder
2 | Set the component to which the `View` contents display is delegated
3 | Add a `ViewProvider`
4 | Set the default `View` name
5 | Set the error `View`
6 | Set the error `View` provider
7 | Set the max navigation history size
8 | Configure the navigator to navigate to default `View` (if availablr) when a view is not available according to current navigation state
9 | Add a `ViewChangeListener`
10 | Build the `ViewNavigator` and bind it to the `UI`

The `ViewNavigator` builder makes available a default `View` provider, which supports a fixed set of `Views` configured using a View name bound to a View class.

Stateful views are supported by this provider. To declare a View as stateful, the StatefulView annotation can be used on the View class.

View instances will be created according to view scope: for stateful views, an instance is created at first request (for each UI) and the same instance is returned to subsequent view requests. On the contrary, for standard views, a new instance is created and returned to navigator for every view request.

To register this view provider and configure the `View` set, the `ViewNavigator` builder method `withView(String viewName, Class<? extends View> viewClass)` can be used.

    UI ui = getUI();
    ViewNavigator.builder() //
        .viewDisplay(ui) //
        .withView("view1", View1.class) (1)
        .withView("view2", View2.class) (2)
        .defaultViewName("view1") (3)
        .buildAndBind(ui);

1 | Register the view class `View1` and bind it the `view1` name
2 | Register the view class `View2` and bind it the `view2` name
3 | Set the `view1` View as the default view

### 14.5. Excluding a View form navigation history

By default, the `ViewNavigator` tracks views navigation history, to made available navigation operations such `navigateBack()` to navigate to the previous view.

To exclude a `View` from the navigation history, skipping such View when a `navigateBack()` operation is performed or the user presses the browser back button, the VolatileView annotation can be used on the `View` class.

    @VolatileView
    class VolatileViewExample implements View {

    }

### 14.6. Opening Views in a `Window`

The `ViewNavigator` API supports displaying a `View` content in an application `Window`. Instead of using the configured view display component, the `View` contents will be displayed in a popup dialog, using the `com.vaadin.ui.Window` component.

The view navigation state is tracked in the navigator history just like any other navigation operation.

To open a `View` in a `Window`, the `navigateInWindow(…​)` view navigator methods can be used.

    ViewNavigator.require().navigateInWindow("myView"); (1)

1 | Opens the View named `myView` in a `Window`

#### 14.6.1. `@WindowView` annotation

The WindowView annotation can be used to declare that a `View` should always be displayed in a `Window` by the `ViewNavigator`.

When the `@WindowView` annotation is found on a `View` class, such `View` will be always opened in a `Window, regardless of the navigation operation that is used.

    @WindowView (1)
    class MyWindowView1 implements View {

    }

    void openTheView() {
      ViewNavigator.require().navigateTo("myView"); (2)
    }

1 | Configure the `View` class to be always displayed in a `Window`
2 | Supposing that the `MyWindowView1` class is bound to the `myView` name, the `ViewNavigator` will display such `View` in a `Window` since the `@WindowView` annotation is found on the view class

#### 14.6.2. View `Window` configuration

When a `View` is displayed in a `Window`, the `Window` component which contains the `View` can be configured in the following ways:

1. Using the provided `ViewWindowConfigurator`: The `ViewNavigator` API provides a `navigateInWindow(…​)` method version which provides a ViewWindowConfigurator API to configure the `Window` component into which the `View` will be displayed.

    ViewNavigator.require().navigateInWindow("myView", configurator -> {
      configurator.fullWidth().caption("Title").closable(false).resizable(false); (1)
    });

1 | Use the `ViewWindowConfigurator` API to configure the `Window` component

2. Using the `@WindowView` annotation attributes: When a `View` is configured to be displayed in a `Window` using the `@WindowView` annotation, the available annotation attributes can be used to configure some basic `Window` component features.

    @WindowView(windowWidth = "50%", windowHeigth = "50%", closable = false, resizable = true) (1)
    class MyWindowView2 implements View {

    }

1 | Use the `@WindowView` annotation attributes to configure the view `Window`

3. Using a `@ViewWindowConfiguration` annotated View method: If a `View` class `public` method is annotated with the `@ViewWindowConfiguration` annotation and accepts a single parameter of ViewWindowConfigurator type, the method is called by the `ViewNavigator`, providing the `ViewWindowConfigurator` instance which can be used to configure the view `Window` component.

    @WindowView
    class MyWindowView3 implements View {

      @ViewWindowConfiguration (1)
      public void configure(ViewWindowConfigurator configurator) {
        configurator.fullWidth().caption("Title").closable(false).resizable(false);
      }

    }

1 | This method will be called by the `ViewNavigator` before displaying the View, allowing to configure the view `Window` component using the provided `ViewWindowConfigurator`

### 14.7. `ViewNavigator` API operations

The `ViewNavigator` API makes available navigation methods to provide a set of parameters to the `View` being activated.

These parameters are serialized in the navigation state String, and are automatically bound to the any `View` class field annotated with the `@ViewParameter` annotation.

See View parameters injection for further informations about `View` parameters injection.

| When using `@ViewParameter` annotated `View` methods, the parameter value types provided to a view navigation method through the name-value Map must be consistent with the corresponding `@ViewParameter` view class field type.

The `ViewNavigator` API provides the following operations for `View` navigation:

- `navigateTo(String viewName, Map<String, Object> parameters)`: navigate to given `View` name, providing an optional Map of parameters with parameters names and corresponding values.

- `navigateTo(String viewName)`: navigate to given `View` name without providing any view parameter.

    ViewNavigator navigator = getViewNavigator();

    navigator.navigateTo("myView"); (1)

    Map<String, Object> parameters = new HashMap<>();
    parameters.put("parameter1", "test");
    parameters.put("parameter2", 34.5);

    navigator.navigateTo("myView", parameters); (2)

1 | Navigate to the view named `myView`
2 | Navigate to the view named `myView` providing a map of parameters (names and values) `navigateInWindow(…​)`: `View` navigation methods that force the View content to be displayed in an `Window`, supporting a `ViewWindowConfiguration` Consumer function to setup the view `Window` features.

    ViewNavigator navigator = getViewNavigator();

    navigator.navigateInWindow("myView"); (1)

    Map<String, Object> parameters = new HashMap<>();
    parameters.put("parameter1", "test");
    parameters.put("parameter2", 34.5);

    navigator.navigateInWindow("myView", windowConfig -> {
      windowConfig.fullWidth();
      windowConfig.styleName("my-window-style");
    }, parameters); (2)

1 | Navigate to the view named `myView` and display the view in a Window
2 | Navigate to the view named `myView` and display the view in a Window, providing a window configuration consumer and a map of parameters Using the `NavigationBuilder` through the `toView(String viewName)` method, which accepts the view name and the optional view parameters using a fluent builder style.

    ViewNavigator navigator = getViewNavigator();

    navigator.toView("myView").withParameter("parameter1", "test").withParameter("parameter2", 34.5).navigate(); (1)

    navigator.toView("myView").navigateInWindow(); (2)

    navigator.toView("myView").navigateInWindow(windowConfig -> {
      windowConfig.fullWidth();
      windowConfig.styleName("my-window-style");
    }); (3)

1 | Navigate to the view named `myView` using given parameters
2 | Navigate to the view named `myView` and display the view in a Window
3 | Navigate to the view named `myView` and display the view in a Window, providing a window configuration consumer The `navigateToDefault()` method can be used to navigate to the default view, if configured. The `navigateBack()` method can be used to navigate back to previous `View`, if any. In no previous `View` is available and a default view is defined, navigator will navigate to the default view.

### 14.8. Sub views

The `ViewNavigator` supports the concept of sub view: a sub view is a `View` which is always displayed using a parent view container, and the sub view display strategy is delegated to the container.

A sub view container is a conventional `View` which implements the SubViewOf interface.

Any sub view must declare its parent container view name using the WindowView annotation.

When the navigation to a sub view is triggered, the `ViewNavigator` first of all will navigate to the declared sub view container, displaying it as a normal `View`, then the `display(View view, String viewName, Map<String, String> parameters)` method of the sub view container is invoked providing the sub view instance, the sub view name and any navigation parameter. At this point, the container should display the sub view contents in a suitable way.

| The `getViewContent(View view)` static method of the `ViewNavigator` interface can be used to obtain the view contents from a `View` instance.

    class SubViewContainerExample extends TabSheet implements SubViewContainer { (1)

      public SubViewContainerExample() {
        super();
        setSizeFull();
      }

      @Override
      public boolean display(View view, String viewName, Map<String, String> parameters)
          throws ViewNavigationException {
        addTab(view.getViewComponent(), viewName, VaadinIcons.PIN);
        return true;
      }

      @Override
      public View getCurrentView() {
        return (View) getSelectedTab();
      }

    }

    @SubViewOf("mycontainer")
    public class SubViewExample extends VerticalLayout implements View { (2)

      public SubViewExample() {
        super();
        setMargin(true);
        addComponent(new Label("The sub view 1"));
      }

    }

1 | A view declared as `SubViewContainer` using a `TabSheet` to display each sub view in a new tab. We suppose this view is bound to the `mycontainer` view name
2 | A sub view bound to the `mycontainer` sub view container using the `@SubViewOf` annotation

### 14.9. Context resources injection

The `ViewNavigator` supports Context resources injection into the `View` instances. A resource available form the Holon platform `Context` registry can be injected in a `View` using the ViewContext annotation on a `View` field.

The resource to be injected is looked up by key, and by the default the resource key is assumed to be the fully qualified class name of the injectable field type. To override this strategy, the `value()` annotation attribute of the `ViewContext` annotation can be used to provide the resource key to look up.

| See the Context documentation for further information about context resources.

    class ViewContextExample implements View {

      @ViewContext
      private LocalizationContext localizationContext;

      @ViewContext
      private AuthContext authContext;

    }

### 14.10. Obtain the current ViewNavigator

The `ViewNavigator` interface provides methods to obtain the current navigator using the following strategy:

- If the `ViewNavigator` is available as Context resource using the default navigator resource key, that instance is returned;

- If a current Vaadin `UI` is available and a `ViewNavigator` is bound to the `UI`, that instance is returned.

| See the Context documentation for further information about context resources.

    Optional<ViewNavigator> navigator = ViewNavigator.getCurrent(); (1)

    ViewNavigator viewNavigator = ViewNavigator.require(); (2)

1 | Try to obtain the `ViewNavigator` from context or current `UI`
2 | Obtain the `ViewNavigator` from context or current `UI`, failing with an exception if not found

### 14.11. Authentication support

The `ViewNavigator` architecture provides support for `View` authentication, relying on the default Holon platform `AuthContext` API.

| See the Realm and AuthContext documentation for information about the Holon platform authentication and authorization architecture.

In order for the authentication to work, an `AuthContext` instance must be available as a context resource, and it will be used to perform user authentication and resource access control, relying on the `Realm` bound to the auth context.

The authentication support is enabled by default, but it can be configured using the `authenticationEnabled(…​)` `ViewNavigator` builder method.

The authentication support is enabled through the standard `com.holonplatform.auth.annotations.Authenticate` annotation, which can be used on a `View` class or on the application `UI` class.

When the `@Authenticate` annotation is used at `UI` level, all the views managed by the navigator bound to such `UI` will be under authentication, and the access to any `View` will be denied if an authenticated subject is not available from the current `AuthContext`.

Each time the navigation to a protected `View` is requested, the `AuthContext` is checked, and if it not authenticated, the following strategy is implemented:

1. An implicit authentication attempt is performed, using the current `VaadinRequest` and the optional authentication schemes which can be specified using the `schemes()` attribute of the `Authenticate` annotation. This behaviour can be used, for example, to support authentication using the current HTTP request and schemes such the `Authorization` HTTP header.

2. If the implicit authentication is not successfull and a valid redirect URI is provided through the `redirectURI()` property of the `Authenticate` annotation, the navigation is redirected to that URI. If the redirect URI does not specify a scheme, or the scheme is equal to the special `view://` scheme, the navigation is redirected to the navigation state specified by the redirect URI (escluding the `view://` part, if present). This way, the redirect URI can be used to delegate to a `View` an explicit authentication entry point (for example using conventional username and password credentials).

| In order for the `View` authentication process to work properly, when the `@Authenticate` annotation is used on one or more specific `View` class (and not at `UI` level), a ViewClassProvider instance has to be bound to each registered `ViewProvider` to provide the `View` class which corresponds to a specific view name. The `ViewNavigator` builder API provides the `viewClassProvider(…​)` method to configure the `ViewClassProvider`. When the Spring integration is enabled and the default `SpringViewNavigator` is used, a default `ViewClassProvider` is automatically configured, without needing to configure it explicitly.

## 15. Spring integration

The `holon-vaadin-spring` artifact provides support and integration with the Spring framework.

Maven coordinates:

    <groupId>com.holon-platform.vaadin</groupId>
    <artifactId>holon-vaadin-spring</artifactId>
    <version>5.4.0</version>

This artifact provides a `ViewNavigator` extension with Spring support, represented by the SpringViewNavigator API.

The `SpringViewNavigator` implementation relies upon the standard Vaadin Spring integration add-on, and supports all its functionalities and configuration features.

See the Vaadin Spring tutorial for the documentation.

The following annotations are available for `View` configuration:

- DefaultView: can be used on a `View` class to declare it as the default view, i.e the view which will be used as target of the `ViewNavigator.navigateToDefault()` method and as a fallback by the `ViewNavigator.navigateBack()` method if no other `View` is available in navigation history.

- ErrorView: can be used on a `View` class to declare it as the default error view, i.e. the `View` to be displayed when no other `View` matches a navigation state.

### 15.1. Default View navigation strategy

When a statically declared default `View` (using for example the `@DefaultView` annotation) is not suitable for an application, the DefaultViewNavigationStrategy interface can be used to implement a custom strategy to provide the default navigation state.

When a `DefaultViewNavigationStrategy` type Spring bean is found in application context, it is automatically configured in View navigator as default view navigation stategy implementation.

### 15.2. Spring view navigator configuration

The `SpringViewNavigator` API provides a builder to create a navigator instance, and can be used to explicitly build and configure a `SpringViewNavigator` instance. The bulder can be obtained through the static `builder()` method of the `SpringViewNavigator` interface.

The easiest way to setup a Spring view navigator, is to use the provided EnableViewNavigator configuration annotation.

The `@EnableViewNavigator` can be used on Spring configuration classes to automatically setup the default Vaadin Spring integration and register a UI-scoped `SpringViewNavigator` bean. The standard `@SpringViewDisplay` annotation can be used to configure the views display component and the default Vaadin Spring `ViewProvider` will be used.

| The `@EnableViewNavigator` annotation includes the standard `com.vaadin.spring.annotation.@EnableVaadin` annotation behaviour, which is not required anymore on configuration classes.

The `@EnableViewNavigator` annotation makes available a number of properties to control the navigator configuration, for example to explicitly configure the default and error views or to set the max navigation history size. See the EnableViewNavigator javadocs for further information.

    @Configuration (1)
    @ComponentScan(basePackageClasses = ViewOne.class) (2)
    @EnableViewNavigator (3)
    @EnableBeanContext (4)
    class SpringConfig {

    }

    @SpringView(name = "view1") (5)
    @DefaultView (6)
    class ViewOne extends VerticalLayout implements View {

    }

    @SpringView(name = "view2") (7)
    @UIScope (8)
    class ViewTwo extends VerticalLayout implements View {

    }

    @SpringUI (9)
    @SpringViewDisplay (10)
    class AppUI extends UI {

      @Autowired
      ViewNavigator navigator; (11)

      @Override
      protected void init(VaadinRequest request) {
        // ...
      }

    }

1 | Declare the class as a Spring configuration class
2 | Set the component scan rule to auto detect the `View` beans
3 | Enable the Spring `ViewNavigator`
4 | Enable the Holon platform Spring context scope, to provide context resource instances as Spring beans
5 | Declare the view as Spring view (which will be automatically registered in the navigator view provider), and bind it to the `view1` name
6 | Declare the view as the default view
7 | Create another view and enable it as a Spring view using the `view2` name
8 | Declare the view bean scope as `UI`
9 | Create the application `UI` and declare it as a Spring `UI`, which will be automatically detected and configured by Spring
10 | Use the `UI` as `View` display container
11 | The `ViewNavigator` will be made avaialable as Spring (UI-scoped) bean, so it can be obtained using dependency injection

### 15.3. View context resources

The EnableViewContext annotation can be used on Spring configuration classes to enable `View` context resource injection using the ViewContext annotation.

See Context resources injection for further information.

### 15.4. View authorization support

In addition to the `ViewNavigator` authentication support (see Authentication support), the Spring view navigator provides View authorization support using default `javax.annotation.security.*` annotations (`@RolesAllowed`, `@PermitAll`, `@DenyAll`).

The authorization support can be enabled using the EnableViewAuthorization annotation and, just like the authentication support, relies on the current `AuthContext` to perform authorization control, so it must be available as a context resource.

| By using the `@EnableBeanContext` configuration annotation, Spring beans can be automatically configured as context resources. See the Spring context scope documentation for further information.

| The default Vaadin Spring `ViewAccessControl` and `ViewInstanceAccessControl` view access control methods are fully supported too, and can be used along with the security annotations.

The AccessDeniedView annotation can be used on a Spring `View` class to declare it as the view to show when the user is not authorized to access a view, either according to a `javax.annotation.security.*` annotation or to a `ViewAccessControl` or `ViewInstanceAccessControl` rule.

    @Configuration
    @ComponentScan(basePackageClasses = ViewOne.class)
    @EnableViewNavigator
    @EnableBeanContext (1)
    @EnableViewAuthorization (2)
    class SpringConfig {

      @Bean (3)
      @VaadinSessionScope
      public AuthContext authContext() {
        AccountProvider ap = id -> {
          // Only a user with username 'username1' is available
          if ("username1".equals(id)) {
            // setup the user password and assign the role 'role1'
            return Optional.of(Account.builder(id).credentials(Credentials.builder().secret("s3cr3t").build())
                .withPermission("role1").build());
          }
          return Optional.empty();
        };
        return AuthContext.create(Realm.builder()
            // authenticator using the AccountProvider
            .withAuthenticator(Account.authenticator(ap))
            // default authorizer
            .withDefaultAuthorizer().build());
      }

    }

    @SpringView(name = "view1")
    @PermitAll (4)
    class ViewOne extends VerticalLayout implements View {

    }

    @SpringView(name = "view2")
    @RolesAllowed("role1") (5)
    class ViewTwo extends VerticalLayout implements View {

    }

    @AccessDeniedView (6)
    @UIScope
    @SpringView(name = "forbidden")
    class AccessDenied extends VerticalLayout implements View {

      private static final long serialVersionUID = 1L;

      private final Label message;

      public AccessDenied() {
        super();
        Components.configure(this).margin()
            .add(message = Components.label().styleName(ValoTheme.LABEL_FAILURE).build());
      }

      @Override
      public void enter(ViewChangeEvent event) {
        message.setValue("Access denied [" + event.getViewName() + "]");
      }

    }

1 | Use `@EnableBeanContext` to enable Spring beans as context resources (in this example, the `AuthContext` bean will be available as context resource)
2 | Enable views authorization using `javax.annotation.security.*` annotations
3 | Configure the `AuthContext` and declare it as a session-scoped Spring bean
4 | Use `@PermitAll` on this view to skip authorization control
5 | Use `@RolesAllowed` to declare that the view is available only for the authenticated subjects with the `role1` role
6 | Create a custom access denied view using the `@AccessDeniedView` annotation

### 15.5. Spring Security support

The `View` access control using the Spring Security `@Secured` annotation can be enabled using the EnableSecuredView annotation.

This access control strategy relies on the Spring Security `SecurityContext` to check current authentication and performs View access control checking current user granted authorities against the security attributes specified through the `@Secured` annotation.

| The Spring Security artifacts must be explicitly included as a project dependency.

## 16. Spring Boot integration

The `holon-vaadin-spring-boot` artifact provides integration with Spring Boot for Vaadin application and view navigator auto configuration.

To enable 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-spring-boot</artifactId>
    <version>5.4.0</version>

The Spring Boot auto-configuration includes the default Spring Boot Vaadin add-on auto configuration features, with the following additional behaviour:

- The configured view navigator will be a Spring `ViewNavigator`.

- The `View` authorization support using the `javax.annotation.security.*` annotations is enabled by default.

- If Spring Security is available and configured, the `@Secured` annotation based `View` access control is enabled.

To disable this auto-configuration feature the `HolonVaadinAutoConfiguration` class can be excluded:

    @EnableAutoConfiguration(exclude={HolonVaadinAutoConfiguration.class})

To disable the Spring Security `@Secured` access control support the `HolonVaadinSpringSecurityAutoConfiguration` class can be excluded:

    @EnableAutoConfiguration(exclude={HolonVaadinSpringSecurityAutoConfiguration.class})

### 16.1. Vaadin servlet configuration

By default, a Holon extension of the Vaadin servlet is auto-configured.

This servlet allows automatic `com.vaadin.server.SessionInitListener` and `com.vaadin.server.SessionDestroyListener` registration if they are defined as Spring beans and made available in the Spring context.

To disable this auto-configuration feature, the `HolonVaadinServletAutoConfiguration` class can be excluded:

    @EnableAutoConfiguration(exclude={HolonVaadinServletAutoConfiguration.class})

### 16.2. Spring Boot starters

The following starter artifacts are available to provide a quick project configuration setup using Maven dependency system:

1. The Vaadin application starter provides the dependencies to the Holon Platform Vaadin Spring Boot integration artifact `holon-vaadin-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.

- The Spring Boot `spring-boot-starter-tomcat` to use Tomcat as the embedded servlet container.

See the Spring Boot starters documentation for details on Spring Boot starters.

Maven coordinates:

    <groupId>com.holon-platform.vaadin</groupId>
    <artifactId>holon-starter-vaadin</artifactId>
    <version>5.4.0</version>

2. The Vaadin application starter using Undertow provides the same dependencies as the default Vaadin application starter, but using Undertow instead of Tomcat as embedded servlet container.

Maven coordinates:

    <groupId>com.holon-platform.vaadin</groupId>
    <artifactId>holon-starter-vaadin-undertow</artifactId>
    <version>5.4.0</version>

## 17. 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`.

## 18. System requirements

### 18.1. Java

The Holon Platform Vaadin module requires Java 8 or higher.

### 18.2. Vaadin

The Holon Platform Vaadin module requires Vaadin 8.1 or higher.