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

Note that this annotation is an experimental feature that may be subject of API change in the near future.

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.

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.

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.

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
        }

    }