Step 10: Validation in dialogs

This step shows you how to validate user input in dialogs.

As you may have noticed, you can add an empty address to the addresses table. This can be considered invalid, and it can be avoided by using Validation, which is a way to tell the user whether the input fits the domain model logic.

dialog validation
Figure 1. Add Address dialog with validation rules

Marking input fields as required

To inform the user which fields have to be filled in, the fields can be visually marked as required. Set the property required to RequiredType.REQUIRED for all fields in AddressPmo.

Specifying the RequiredType will only display a blue point. It does not prevent the user from leaving the field empty, nor will it display the validation rule that is violated by doing so.

The finished implementation should look like this:

AddressPmo.java
@UITextField(..., required = RequiredType.REQUIRED)
public void street() {
...

@UITextField(..., required = RequiredType.REQUIRED)
public void streetNumber() {
...

@UITextField(..., required = RequiredType.REQUIRED)
public void postalCode() {
...

@UITextField(..., required = RequiredType.REQUIRED)
public void city() {
...

@UITextField(..., required = RequiredType.REQUIRED)
public void country() {
...

If you run your application, you should see a blue point next to the label of each field:

dialog
Figure 2. Add Address dialog with blue points at required fields

Validating the input fields

Validations typically have a justification in the domain model. If for example an attribute is mandatory, this information should be handled by the implementation in the domain model so that all applications that use the same model follow the same logic.

In this case, the domain model class Address implements a method validate(). This method returns a list of validation messages that contain the justification as well as which attributes of which objects they refer to. The only thing left for you to do is to transfer these messages to the fields in the UI.

In linkki, displaying and distributing validation messages are handled by so-called ValidationServices. Whenever a dialog is created with the help of a PmoBasedDialogFactory, it is possible to pass a ValidationService that is used in all dialogs created by that factory.

Implement the validation in the method AddressPage.createNewAddress:

  1. Assign a lambda expression, in which address.validate() is passed to org.linkki.ips.messages.MessageConverter.convert(), to a variable validationService of type ValidationService .

  2. Assign a new instance of PmoBasedDialogFactory, with validationService passed as the argument, to a variable dialogFactory of type PmoBasedDialogFactory.

  3. Use dialogFactory when creating the OkCancelDialog.

To be able to use the MessageConverter you need to add the following dependency:

<dependency>
    <groupId>org.linkki-framework</groupId>
    <artifactId>linkki-ips-vaadin-flow</artifactId>
    <version>${linkki.version}</version>
</dependency>

The finished implementation should look like this:

AddressPage.java
public void createNewAddress() {
    ...
    ValidationService validationService = () -> MessageConverter.convert(address.validate());
    PmoBasedDialogFactory dialogFactory = new PmoBasedDialogFactory(validationService);
    OkCancelDialog addressDialog =
            dialogFactory
                    .newOkCancelDialog("Add Address", okHandler, dialogPmo);
    ...
}

If you run your application and try to add an address without filling in all the fields, you should get an error saying e.g. "The field Street must not be empty.".

dialog validation
Figure 3. Add Address dialog with validation rules