3.5.1.7. Валидация в экранах
Бин ScreenValidation может использоваться для запуска валидации в экранах. Он имеет следующие методы:
-
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, для которой мы можем определить аннотацию уровня класса, для проверки того, что дата Start date должна быть раньше даты End date.Сущность Event@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()- показывает стандартный диалог несохраненных изменений ("Вы действительно хотите закрыть экран?") с кнопками Да и Нет. Используется в экране редактораStandardEditor. МетодshowUnsavedChangesDialog()имеет обработчик, который реагирует на действия пользователя (кнопку, которую он нажал):screenValidation.showUnsavedChangesDialog(this, action) .onDiscard(() -> result.resume(closeWithDiscard())) .onCancel(result::fail); -
showSaveConfirmationDialog()- показывает стандартный диалог подтверждения сохранения измененных данных ("Сохранить изменения перед закрытием экрана?") с кнопками Сохранить, Не сохранять, Отмена. Используется в экране редактораStandardEditor. МетодshowSaveConfirmationDialog()имеет обработчик, который реагирует на действия пользователя (кнопку, которую он нажал):screenValidation.showSaveConfirmationDialog(this, action) .onCommit(() -> result.resume(closeWithCommit())) .onDiscard(() -> result.resume(closeWithDiscard())) .onCancel(result::fail);
Вы можете настроить тип диалога с помощью свойства приложения cuba.gui.useSaveConfirmation.