Application Framework

Dialogs

Dependency linkki-application-framework is needed.

Creating dialogs with PMOs using layout annotation

Dialogs can be created with PMOs annotated with any layout annotation when using PmoBasedDialogFactory. Instances of PmoBasedDialogFactory with a pre-configured IpsPropertyDispatcherFactory can be created using IpsDialogCreator#create() or IpsDialogCreator#with(ValidationService) methods.

PMO classes without any layout annotation are not supported when using PmoBasedDialogFactory
Creating a dialog using PmoBasedDialogFactory
            new PmoBasedDialogFactory().openOkDialog("Dialog containing @UIVerticalLayout",
                                                     new VerticalLayoutTestContentPmo());
PMO using @UIVerticalLayout
    @UIVerticalLayout
    private static class VerticalLayoutTestContentPmo {
        @UILabel(position = 0)
        public String getText() {
            return "Some text";
        }
    }

Creating dialogs on button click

Sometimes, a value or a grid item should not be edited directly. Instead, a dialog should be opened upon a button click in which the user can edit the value in a more complex form. To implement this use case, BindingContext#modelChanged often needs to be passed to the PMO to update the underlying BindingContext after the OK button was clicked.

@UIOpenDialogButton with DialogPmo

The UI annotation @UIOpenDialogButton resolves this inconvenience. The annotated method returns a DialogPmo that is used to create the dialog that is opened upon button click. For use with a Faktor-IPS model object, the abstract class IpsDialogPmo provides a partial implementation of DialogPmo. When the user clicks on the OK button, the underlying BindingContext is updated automatically.

Dialog created with @UIOpenDialogButton
    @UIOpenDialogButton(position = 30, caption = "UIOpenDialogButton with DialogPmo")
    public DialogPmo getAddModelObjectDialog() {
        return new AddModelObjectDialogPmo(this::saveNewModelObject);
    }

The following properties are defined in the implementation of the DialogPmo:

  • The caption used to create the dialog.

  • The OK handler that is called when pressing the dialogs OK button.

  • The PMO for the content of the dialog.

  • A validate method that returns a MessageList containing validation messages that are shown in the dialog. By default, no validation is executed.

  • The PropertyDispatcherFactory that handles the communication between properties and their behaviour.

  • Combine this annotation with @SectionHeader to place the button in the header of a section.

  • To display an icon instead of a caption, set caption = "" or captionType = CaptionType.NONE and use @BindIcon to define the icon.

  • DialogPmo can be used to define dialogs even if @UIOpenDialogButton is not used.

Example DialogPmo and ContentPmo
    static class AddModelObjectDialogPmo extends IpsDialogPmo {

        private final NewModelObjectPmo contentPmo;
        private final Consumer<IpsModelObject> saveModelObject;

        public AddModelObjectDialogPmo(Consumer<IpsModelObject> saveModelObject) {
            this.saveModelObject = saveModelObject;
            this.contentPmo = new NewModelObjectPmo();
        }

        @Override
        public String getCaption() {
            return "New model object";
        }

        @Override
        public Handler getOkHandler() {
            return () -> saveModelObject.accept(contentPmo.getModelObject());
        }

        @Override
        public MessageList getIpsMessages() {
            return contentPmo.getModelObject()
                    .validate(new ValidationContext(UiFramework.getLocale(), this.getClass().getClassLoader(),
                            new DefaultGenericAttributeValidationConfiguration(Locale.GERMANY,
                                    Marker.REQUIRED_INFORMATION_MISSING)));
        }

        @Override
        public NewModelObjectPmo getContentPmo() {
            return contentPmo;
        }
    }

    @UISection
    static class NewModelObjectPmo {

        private final IpsModelObject modelObject;

        public NewModelObjectPmo() {
            this.modelObject = new IpsModelObject();
        }

        @ModelObject
        public IpsModelObject getModelObject() {
            return modelObject;
        }

        @UITextField(position = 10, modelAttribute = IpsModelObject.PROPERTY_DECIMAL, required = RequiredType.REQUIRED)
        public void decimal() {
            // Model Binding
        }

    }
@UIOpenDialogButton with a Function

Alternatively, the annotated method can also return Function<Handler, OkCancelDialog> for cases where the dialog is not defined with a PMO. The function’s argument is the model changed handler that updates the binding context and the created dialog must make sure that this handler is called when the OK button is clicked.

This is useful when:

  • The dialog needs to be customized, which requires direct control over the dialog creation

  • An existing dialog that was not created with a DialogPmo should be reused

  • The dialog should only be shown under certain conditions — the annotated method may return null in this case, which still triggers a binding context update

Dialog created with @UIOpenDialogButton using Function<Handler, OkCancelDialog>
    @UIOpenDialogButton(position = 40, caption = "UIOpenDialogButton with Function<Handler, OkCancelDialog>")
    public Function<Handler, OkCancelDialog> getConfirmation() {
        return update -> new ConfirmationDialog("ConfirmationDialog",
                update.compose(this::saveNewZeroModelObject),
                new Text("Create a new model object with decimal = 0."));
    }