对话框

Dialogs 接口用来展示标准的对话框窗口。对话框窗口是一个小的弹出窗口,可以在当前页面叠加展示信息或者 UI 元素。

使用流式接口可以创建和展示对话框,入口方法是 createMessageDialog()createOptionDialog()createInputDialog()

消息对话框

消息对话框可以为用户展示某些消息。

message dialog

下面示例中,当用户点击一个按钮时,展示一个消息对话框:

@Autowired
private Dialogs dialogs;

@Subscribe("messageDialogButton")
public void onHelloButtonClick(ClickEvent<Button> event) {
    dialogs.createMessageDialog()
            .withHeader("Success") (1)
            .withText("Invitation sent successfully") (2)
            .open();
}
1 添加对话框标题。
2 添加消息内容。

文本格式化

文本的格式化可以通过 HTML 实现。对话框可以通过 withContent() 方法展示 HTML 内容。给定的 HTML 会封装在组件中:

@Autowired
private Dialogs dialogs;

Html htmlContent = new Html("<p>Here starts a paragraph. A new line starts after this.<br />" +
        "<b>This text is bold.</b> <i>This text is italic.</i></p>");

@Subscribe("htmlContentButton")
public void onHtmlContentButtonClick(ClickEvent<Button> event) {
    dialogs.createMessageDialog()
            .withHeader("HTML Formatting")
            .withContent(htmlContent)
            .open();
}

显示设置

使用下列方法可以对消息对话框的外观显示和行为进行设置:

  • withModal() - 如果该方法设置 false,则对话框不以模态框方式展示,也就是说,用户还可以与应用的其他部分进行交互。对话框默认为模态框展示。

  • withCloseOnOutsideClick() - 当设置为 true 时,如果对话框是模态展示,则支持用户通过点击对话框外的区域进行关闭。

  • withWidth()withHeight() - 设置对话框的大小。

示例:

@Autowired
private Dialogs dialogs;

@Subscribe("customDialogButton")
public void onSanitizeButtonClick(ClickEvent<Button> event) {
    dialogs.createMessageDialog()
            .withHeader("Information")
            .withText("This is a custom dialog")
            .withCloseOnOutsideClick(true)
            .withWidth("600px")
            .withHeight("200px")
            .open();
}

选项对话框

选项对话框能展示消息和一组用户交互的按钮。

option dialog

使用 withActions() 方法提供 操作,每个操作都由对话框中的一个按钮展示。示例:

@Autowired
private Dialogs dialogs;

@Subscribe("selectOptionButton")
public void onSelectOptionButtonClick(ClickEvent<Button> event) {
    dialogs.createOptionDialog()
            .withHeader("Please confirm")
            .withText("Do you really want to add a customer?")
            .withActions(
                    new DialogAction(DialogAction.Type.YES)
                            .withHandler(e -> addCustomer()), (1)
                    new DialogAction(DialogAction.Type.NO)
            )
            .open();
}
1 如果点击 Yes,则对话框关闭并调用 addCustomer() 操作方法。

DialogAction 基类可以创建标准操作。支持 5 种通过 DialogAction.Type 枚举类型定义的操作:OKCANCELYESNOCLOSE。按钮的名称从 消息包 获取。

后台任务对话框

后台任务对话框为长时间运行的任务提供了用户友好的体验,用户可以在对话框中查看进度并在需要时可以取消操作。

更多关于后台任务机制的内容,请参阅 后台任务 部分。
backgroundtask dialog

配置对话框时,需使用一个后台任务对象:

@Autowired
private Dialogs dialogs;

@Subscribe(id = "backgroundTaskButton", subject = "singleClickListener")
public void onBackgroundTaskClick(final ClickEvent<JmixButton> event) {
    dialogs.createBackgroundTaskDialog(new SampleTask(15, this, 10)) (1)
            .withHeader("Background task running")
            .withText("Please wait until the task is complete")
            .withTotal(10) (2)
            .withCancelAllowed(true) (3)
            .open();
}

protected class SampleTask extends BackgroundTask<Integer, Void> {
    int count;
    public SampleTask(long timeoutSeconds, View<?> view, int count) {
        super(timeoutSeconds, view);
        this.count = count;
    }

    @Override
    public Void run(TaskLifeCycle<Integer> taskLifeCycle) throws Exception {
        for (int i = 1; i < count + 1; i++) {
            Thread.sleep(1000);
            taskLifeCycle.publish(i);
        }
        return null;
    }
}
1 将后台任务对象传递给对话框。
2 根据任务完成的数量设置进度条。
3 支持用户中断操作。

输入对话框

输入对话框是一个多功能的工具,可以使用 API 构建输入表单,摆脱为琐碎的数据输入创建界面的麻烦。支持不同类型数据的输入、验证输入数据以及为用户提供不同的操作。

input dialog

下面我们看几个例子。

标准参数

使用 withParameters() 方法添加参数,每个参数都会在对话框中显示为一个输入框。 下面的示例中,输入对话框带有标准类型的参数和标准的 OK/Cancel 操作:

@Autowired
private Dialogs dialogs;

@Subscribe("standardParametersButton")
public void onStandardParametersButtonClick(ClickEvent<Button> event) {
    dialogs.createInputDialog(this)
            .withHeader("Enter values")
            .withParameters(
                    stringParameter("name").withLabel("Name").withRequired(true), (1)
                    intParameter("amount").withLabel("Amount").withDefaultValue(1), (2)
                    entityParameter("user", User.class).withLabel("User"), (3)
                    enumParameter("status", OnboardingStatus.class).withLabel("Status") (4)
            )
            .withActions(DialogActions.OK_CANCEL) (5)
            .withCloseListener(closeEvent -> {
                if (closeEvent.closedWith(DialogOutcome.OK)) { (6)
                    String name = closeEvent.getValue("name"); (7)
                    int amount = closeEvent.getValue("amount");
                    User user = closeEvent.getValue("user");
                    OnboardingStatus status = closeEvent.getValue("status");
                    // process entered values...
                }
            })
            .open();

}
1 指定一个必填的字符串参数。
2 指定一个带有默认值的整型参数。
3 指定一个实体参数。
4 指定一个枚举参数。
5 指定标准的 OK/Cancel 操作,放置于对话框底部。
6 在关闭事件监听器中,我们可以检查用户使用了什么操作。
7 关闭事件包含了输入的值,可以通过参数标识符进行获取。

自定义参数

下面的示例展示了创建自定义参数并支持用户通过 combobox 进行选择:

@Autowired
private Dialogs dialogs;

@Autowired
private DataManager dataManager;
@Autowired
private UiComponents uiComponents;

@Subscribe("customParameterButton")
public void onCustomParameterButtonClick(ClickEvent<Button> event) {
    dialogs.createInputDialog(this)
            .withHeader("Enter values")
            .withParameters(
                    stringParameter("name").withLabel("Name").withRequired(true),
                    intParameter("amount").withLabel("Amount").withDefaultValue(1),
                    parameter("user") (1)
                            .withLabel("User")
                            .withField(() -> {
                                EntityComboBox<User> field = uiComponents.create(EntityComboBox.class); (2)
                                field.setItems(dataManager.load(User.class).all().list()); (3)
                                field.setWidthFull();
                                return field;
                            }),
                    enumParameter("status", OnboardingStatus.class).withLabel("Status")
            )
            .withActions(DialogActions.OK_CANCEL).withCloseListener(closeEvent -> {
                if (closeEvent.closedWith(DialogOutcome.OK)) {
                    String name = closeEvent.getValue("name");
                    int amount = closeEvent.getValue("amount");
                    User user = closeEvent.getValue("user");
                    OnboardingStatus status = closeEvent.getValue("status");
                    // process entered values...
                }
            })
            .open();
}
1 指定一个自定义参数。
2 为自定义参数创建 combobox。
3 为 combobox 加载选项。

自定义校验

对话框默认带有一些基础的校验:验证输入值的类型、检查必填项是否为空。在这之上,可以添加其他通用的自定义校验。

下面的示例添加了一个校验,要求至少输入一个参数:

@Autowired
private Dialogs dialogs;

@Subscribe("validationButton")
public void onValidationButtonClick(ClickEvent<Button> event) {
    dialogs.createInputDialog(this)
            .withHeader("Enter at least one value")
            .withParameters(
                    stringParameter("name").withLabel("Name").withRequired(true),
                    entityParameter("User", User.class).withLabel("User")
            )
            .withValidator(context -> { (1)
                String name = context.getValue("name"); (2)
                User user = context.getValue("user");
                if (Strings.isNullOrEmpty(name) && user == null) {
                    return ValidationErrors.of("Enter name or select a customer"); (3)
                }
                return ValidationErrors.none();
            })
            .withActions(DialogActions.OK_CANCEL)
            .withCloseListener(closeEvent -> {
                if (closeEvent.closedWith(DialogOutcome.OK)) {
                    String name = closeEvent.getValue("name");
                    User user = closeEvent.getValue("user");
                    // process entered values...
                }
            })
            .open();
}
1 自定义验证逻辑,保证至少有一个参数。
2 验证器内,参数可以从 context 对象获取。
3 如果没有输入任何参数,则返回验证错误。