3.5.6. 对话框消息
Dialogs
接口设计用来展示标准对话框窗口。其 createMessageDialog()
、createOptionDialog()
和 createInputDialog()
方法是流式 API 的入口点,可以用来创建和显示对话框。
- 消息对话框
-
下面的例子中,当用户点击按钮时,会显示一个消息对话框:
@Inject private Dialogs dialogs; @Subscribe("showDialogBtn") protected void onShowDialogBtnClick(Button.ClickEvent event) { dialogs.createMessageDialog().withCaption("Information").withMessage("Message").show(); }
使用
withMessage()
方法传递消息文本。可以在消息中使用
\n
字符来换行。如果要显示 HTML,可以用withContentMode()
方法带ContentMode.HTML
参数。当使用 HTML 时,别忘了转移数据内容以防恶意代码注入。为
withHtmlSanitizer()
方法传参true
可以启用对话框内容的 HTML 清理功能。此时,必须为withContentMode()
方法传递ContentMode.HTML
参数。protected static final String UNSAFE_HTML = "<i>Jackdaws </i><u>love</u> <font size=\"javascript:alert(1)\" " + "color=\"moccasin\">my</font> " + "<font size=\"7\">big</font> <sup>sphinx</sup> " + "<font face=\"Verdana\">of</font> <span style=\"background-color: " + "red;\">quartz</span><svg/onload=alert(\"XSS\")>"; @Inject private Dialogs dialogs; @Subscribe("showMessageDialogOnBtn") public void onShowMessageDialogOnBtnClick(Button.ClickEvent event) { dialogs.createMessageDialog() .withCaption("MessageDialog with Sanitizer") .withMessage(UNSAFE_HTML) .withContentMode(ContentMode.HTML) .withHtmlSanitizer(true) .show(); } @Subscribe("showMessageDialogOffBtn") public void onShowMessageDialogOffBtnClick(Button.ClickEvent event) { dialogs.createMessageDialog() .withCaption("MessageDialog without Sanitizer") .withMessage(UNSAFE_HTML) .withContentMode(ContentMode.HTML) .withHtmlSanitizer(false) .show(); }
withHtmlSanitizer()
接收的参数会覆盖全局的 cuba.web.htmlSanitizerEnabled 配置。使用下面的方法可以自定义消息对话框的外观和行为:
-
withModal()
- 如果使用false
,对话框不以模态窗展示,此时用户可以与应用程序的其它部分交互。
-
withCloseOnClickOutside()
- 如果使用true
,并且窗口是模态展示时,用户可以点击对话框之外的地方来关闭对话框。
-
withMaximized()
– 当设置为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 - 关闭事件包含输入的值,可以用参数标识符获取。
-