3.5.6. 对话框消息
Dialogs
接口设计用来展示标准对话框窗口。其 createMessageDialog()
、createOptionDialog()
和 createInputDialog()
方法是流式 API 的入口点,可以用来创建和显示对话框。
对话框的展示可以使用带 $cuba-window-modal-*
前缀的 SCSS 变量进行自定义。可以在创建一个 主题扩展 或者一个 自定义主题 之后在可视化编辑器里修改这些变量的值。
消息对话框
下面的例子中,当用户点击按钮时,会显示一个消息对话框:
@Inject
private Dialogs dialogs;
@Subscribe("showDialogBtn")
protected void onShowDialogBtnClick(Button.ClickEvent event) {
dialogs.createMessageDialog().withCaption("Information").withMessage("Message").show();
}
可以在消息中使用 \n
字符来换行。如果要显示 HTML,可以用 withContentMode()
方法带 ContentMode.HTML
参数。当使用 HTML 时,别忘了转移数据内容以防恶意代码注入。
使用下面的方法可以自定义消息对话框的外观和行为:
withModal()
- 如果使用false
,对话框不以模态窗展示,此时用户可以与应用程序的其它部分交互。withCloseOnClickOutside()
- 如果使用true
,并且窗口是模态展示时,用户可以点击对话框之外的地方来关闭对话框。withWidth()
,withHeight()
可以设置需要的弹窗大小。
示例:
@Inject
private Dialogs dialogs;
@Subscribe("showDialogBtn")
protected void onShowDialogBtnClick(Button.ClickEvent event) {
dialogs.createMessageDialog()
.withCaption("Information")
.withMessage("<i>Message<i/>")
.withContentMode(ContentMode.HTML)
.withCloseOnClickOutside(true)
.withWidth("100px")
.withHeight("300px")
.show();
}
选项对话框
选项对话框展示了一个消息和一组用户交互的按钮。使用 withActions()
方法可以提供操作,每个操作在对话框中以按钮的形式展示。示例:
@Inject
private Dialogs dialogs;
@Subscribe("showDialogBtn")
protected void onShowDialogBtnClick(Button.ClickEvent event) {
dialogs.createOptionDialog()
.withCaption("Confirm")
.withMessage("Are you sure?")
.withActions(
new DialogAction(DialogAction.Type.YES, Action.Status.PRIMARY).withHandler(e -> {
doSomething();
}),
new DialogAction(DialogAction.Type.NO)
)
.show();
}
当按钮被点击时,对话框会关闭并且调用相应操作的 actionPerform()
方法。
DialogAction
基类设计用来创建带有标准名称和图标的操作。支持五种使用 DialogAction.Type
枚举定义的操作类型:OK
,CANCEL
,YES
,NO
,CLOSE
。对应的按钮名称通过主语言消息包获取。
DialogAction
构造器的第二个参数用来为操作的按钮设置特殊的可视化样式。c-primary-action
样式提供的 Status.PRIMARY
会高亮对应的按钮并使得它被选中。如果对话框中有多个操作使用了 Status.PRIMARY
,只有第一个操作的按钮能使用正确的样式和图标。
输入对话框
输入对话框是一个多功能的工具,可以使用 API 构建输入表单,摆脱以前创建界面做数据输入。支持不同类型数据的输入、验证输入数据以及为用户提供不同的操作。
下面我们看几个例子。
带有标准类型参数和 OK/Cancel 按钮的输入对话框:
@Inject
private Dialogs dialogs;
@Subscribe("showDialogBtn")
private void onShowDialogBtnClick(Button.ClickEvent event) {
dialogs.createInputDialog(this)
.withCaption("Enter some values")
.withParameters(
InputParameter.stringParameter("name")
.withCaption("Name").withRequired(true), (1)
InputParameter.doubleParameter("quantity")
.withCaption("Quantity").withDefaultValue(1.0), (2)
InputParameter.entityParameter("customer", Customer.class)
.withCaption("Customer"), (3)
InputParameter.enumParameter("status", Status.class)
.withCaption("Status") (4)
)
.withActions(DialogActions.OK_CANCEL) (5)
.withCloseListener(closeEvent -> {
if (closeEvent.closedWith(DialogOutcome.OK)) { (6)
String name = closeEvent.getValue("name"); (7)
Double quantity = closeEvent.getValue("quantity");
Optional<Customer> customer = closeEvent.getOptional("customer"); (8)
Status status = closeEvent.getValue("status");
// process entered values...
}
})
.show();
}
1 - 指定一个必填的字符串参数。 2 - 指定一个带有默认值的双浮点参数。 3 - 指定一个实体参数。 4 - 指定一个枚举参数。 5 - 指定一组用按钮表示的操作,并放在对话框底部。 6 - 在关闭事件监听器中,我们可以检查用户使用了什么操作。 7 - 关闭事件包含了输入的值,可以通过参数标识符进行获取。 8 - 可以得到一个用 Optional
包装的值。自定义参数的输入对话框:
@Inject
private Dialogs dialogs;
@Inject
private UiComponents uiComponents;
@Subscribe("showDialogBtn")
private void onShowDialogBtnClick(Button.ClickEvent event) {
dialogs.createInputDialog(this)
.withCaption("Enter some values")
.withParameters(
InputParameter.stringParameter("name").withCaption("Name"),
InputParameter.parameter("customer") (1)
.withField(() -> {
LookupField<Customer> field = uiComponents.create(
LookupField.of(Customer.class));
field.setOptionsList(dataManager.load(Customer.class).list());
field.setCaption("Customer"); (2)
field.setWidthFull();
return field;
})
)
.withActions(DialogActions.OK_CANCEL)
.withCloseListener(closeEvent -> {
if (closeEvent.closedWith(DialogOutcome.OK)) {
String name = closeEvent.getValue("name");
Customer customer = closeEvent.getValue("customer"); (3)
// process entered values...
}
})
.show();
}
1 - 指定一个自定义参数 2 - 在创建的组件中指定自定义参数的标题。 3 - 跟标准的参数一样的方法获取自定义参数的值。 使用自定义操作的输入对话框:
@Inject
private Dialogs dialogs;
@Subscribe("showDialogBtn")
private void onShowDialogBtnClick(Button.ClickEvent event) {
dialogs.createInputDialog(this)
.withCaption("Enter some values")
.withParameters(
InputParameter.stringParameter("name").withCaption("Name")
)
.withActions( (1)
InputDialogAction.action("confirm")
.withCaption("Confirm")
.withPrimary(true)
.withHandler(actionEvent -> {
InputDialog dialog = actionEvent.getInputDialog();
String name = dialog.getValue("name"); (2)
dialog.closeWithDefaultAction(); (3)
// process entered values...
}),
InputDialogAction.action("refuse")
.withCaption("Refuse")
.withValidationRequired(false)
.withHandler(actionEvent ->
actionEvent.getInputDialog().closeWithDefaultAction())
)
.show();
}
1 - withActions()
方法能接收一组用户自定义的操作。2 - 在操作处理器中,可以从对话框获取参数值。 3 - 自定义操作不会关闭对话框本身,所以需要同时手动关闭。 带自定义校验的输入对话框
@Inject
private Dialogs dialogs;
@Subscribe("showDialogBtn")
private void onShowDialogBtnClick(Button.ClickEvent event) {
dialogs.createInputDialog(this)
.withCaption("Enter some values")
.withParameters(
InputParameter.stringParameter("name").withCaption("Name"),
InputParameter.entityParameter("customer", Customer.class).withCaption("Customer")
)
.withValidator(context -> { (1)
String name = context.getValue("name"); (2)
Customer customer = context.getValue("customer");
if (Strings.isNullOrEmpty(name) && customer == null) {
return ValidationErrors.of("Enter name or select a customer");
}
return ValidationErrors.none();
})
.withActions(DialogActions.OK_CANCEL)
.withCloseListener(closeEvent -> {
if (closeEvent.closedWith(DialogOutcome.OK)) {
String name = closeEvent.getValue("name");
Customer customer = closeEvent.getValue("customer");
// process entered values...
}
})
.show();
}
1 - 需要自定义校验确保至少输入了一个参数。 2 - 在校验器中,参数值可以通过上下文对象获取。 带有
FileDescriptor
参数的输入对话框:@Inject
private Dialogs dialogs;
@Subscribe("showDialogBtn")
public void onShowDialogBtnClick(Button.ClickEvent event) {
dialogs.createInputDialog(this)
.withCaption("Select the file")
.withParameters(
InputParameter.fileParameter("fileField") (1)
.withCaption("File"))
.withCloseListener(closeEvent -> {
if (closeEvent.closedWith(DialogOutcome.OK)) {
FileDescriptor fileDescriptor = closeEvent.getValue("fileField"); (2)
}
})
.show();
}
1 - 指定一个 FileDescriptor
参数。2 - 关闭事件包含输入的值,可以用参数标识符获取。