3.5.1.7. 界面中的验证
ScreenValidation
bean 可以用来运行界面中的验证逻辑,有如下方法:
-
ValidationErrors validateUiComponents()
,默认在StandardEditor
,InputDialog
和MasterDetailScreen
提交改动时使用。该方法接收一组界面组件或者一个组件容器作为参数,返回这些组件中的验证错误(ValidationErrors
对象)。validateUiComponents()
方法还可以用在其他任意的界面中。示例:@UiController("demo_DemoScreen") @UiDescriptor("demo-screen.xml") public class DemoScreen extends Screen { @Inject private ScreenValidation screenValidation; @Inject private Form demoForm; @Subscribe("validateBtn") public void onValidateBtnClick(Button.ClickEvent event) { ValidationErrors errors = screenValidation.validateUiComponents(demoForm); if (!errors.isEmpty()) { screenValidation.showValidationErrors(this, errors); return; } } }
-
showValidationErrors()
- 显示所有的错误和有问题的组件。该方法接收界面和ValidationErrors
对象作为参数。默认在StandardEditor
,InputDialog
和MasterDetailScreen
中使用。 -
validateCrossFieldRules()
- 接收界面和实体作为参数,返回ValidationErrors
对象。执行跨字段验证规则。如果编辑界面的约束中包含UiCrossFieldChecks
并且所有的属性级别验证通过,则会在提交时,进行类级别约束的验证(更多信息参考 自定义约束 章节)。可以使用控制器的setCrossFieldValidate()
方法禁用此类验证。默认情况下,在StandardEditor
,MasterDetailScreen
以及DataGrid
的编辑界面使用。另外,validateCrossFieldRules()
方法也可以用在任意界面中。举个例子,对于
Event
实体,我们可以定义类级别注解@EventDate
来检查 Start date 必须小于 End date。Event entity@Table(name = "DEMO_EVENT") @Entity(name = "demo_Event") @NamePattern("%s|name") @EventDate(groups = {Default.class, UiCrossFieldChecks.class}) public class Event extends StandardEntity { private static final long serialVersionUID = 1477125422077150455L; @Column(name = "NAME") private String name; @Temporal(TemporalType.TIMESTAMP) @Column(name = "START_DATE") private Date startDate; @Temporal(TemporalType.TIMESTAMP) @Column(name = "END_DATE") private Date endDate; ... }
注解定义如下:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = EventDateValidator.class) public @interface EventDate { String message() default "The Start date must be earlier than the End date"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
EventDateValidatorpublic class EventDateValidator implements ConstraintValidator<EventDate, Event> { @Override public boolean isValid(Event event, ConstraintValidatorContext context) { if (event == null) { return false; } if (event.getStartDate() == null || event.getEndDate() == null) { return false; } return event.getStartDate().before(event.getEndDate()); } }
然后可以在任意界面中使用
validateCrossFieldRules()
方法。@UiController("demo_DemoScreen") @UiDescriptor("demo-screen.xml") public class DemoScreen extends Screen { @Inject protected Metadata metadata; @Inject protected ScreenValidation screenValidation; @Inject protected TimeSource timeSource; @Subscribe("validateBtn") public void onValidateBtnClick(Button.ClickEvent event) { Event event = metadata.create(Event.class); event.setName("Demo event"); event.setStartDate(timeSource.currentTimestamp()); // We make the endDate earlier than the startDate event.setEndDate(DateUtils.addDays(event.getStartDate(), -1)); ValidationErrors errors = screenValidation.validateCrossFieldRules(this, event); if (!errors.isEmpty()) { screenValidation.showValidationErrors(this, errors); } } }
-
showUnsavedChangesDialog()
- 为没保存的数据显示标准对话框("Do you want to discard unsaved changes?" - “您要放弃更改吗?”),带有 Yes - 是 和 No - 否 按钮。用在StandardEditor
中。showUnsavedChangesDialog()
带有处理用户操作(点击的按钮)的处理器:screenValidation.showUnsavedChangesDialog(this, action) .onDiscard(() -> result.resume(closeWithDiscard())) .onCancel(result::fail);
-
showSaveConfirmationDialog()
- 为确认保存更改的数据显示标准对话框("Do you want to save changes before close?" - “关闭页面前需要保存修改吗?”)带有 Save - 保存,Do not save - 不保存 和 Cancel - 取消 按钮。用在StandardEditor
中。showSaveConfirmationDialog()
带有处理用户操作(点击的按钮)的处理器:screenValidation.showSaveConfirmationDialog(this, action) .onCommit(() -> result.resume(closeWithCommit())) .onDiscard(() -> result.resume(closeWithDiscard())) .onCancel(result::fail);
可以用 cuba.gui.useSaveConfirmation 应用程序属性修改对话框类型。