Screen Validation
The ScreenValidation
bean is used to run validation in screens. It has the following methods:
-
validateUiComponents()
is used by default when committing changes in theStandardEditor
,InputDialog
, andMasterDetailScreen
. The method accepts a collection of components or a component container and returns validation errors in these components -ValidationErrors
object. ThevalidateUiComponents()
method also can be used in an arbitrary screen. For example:@UiController("sample_DemoScreen") @UiDescriptor("demo-screen.xml") public class DemoScreen extends Screen { @Autowired private ScreenValidation screenValidation; @Autowired 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()
- displays a notification with all errors and problematic components. The method accepts the screen andValidationErrors
object. It is also used by default in theStandardEditor
,InputDialog
, andMasterDetailScreen
. -
validateCrossFieldRules()
- accepts a screen and an entity and returns theValidationErrors
object. By default, it is used in theStandardEditor
,MasterDetailScreen
, and in the editor of theDataGrid
. This method performs cross-field validation rules.Editor screens validate class-level constraints on the commit if the constraints include the
UiCrossFieldChecks
group and all attribute-level constraint checks are successful. You can disable this type of validation using thesetCrossFieldValidate()
method of the controller. ThevalidateCrossFieldRules()
method also can be used in an arbitrary screen.As an example, let’s look at the
Event
entity for which we can define a class-level annotation@EventDate
to check that the start date must be lower than the end date:@JmixEntity @Table(name = "SAMPLE_EVENT") @Entity(name = "sample_Event") @EventDate(groups = {Default.class, UiCrossFieldChecks.class}) public class Event { @JmixGeneratedValue @Column(name = "ID", nullable = false) @Id private UUID id; @Column(name = "NAME") @InstanceName private String name; @Column(name = "START_DATE") @Temporal(TemporalType.TIMESTAMP) private Date startDate; @Column(name = "END_DATE") @Temporal(TemporalType.TIMESTAMP) private Date endDate; // ...
The annotation definition looks like this:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = EventDateValidator.class) public @interface EventDate { String message() default "Start date must be earlier than the end date"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
Here is the
EventDateValidator
class:public 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()); } }
Then you can use the
validateCrossFieldRules()
method in an arbitrary screen.@UiController("sample_DemoScreen") @UiDescriptor("demo-screen.xml") public class DemoScreen extends Screen { @Autowired private ScreenValidation screenValidation; @Autowired protected Metadata metadata; @Autowired protected TimeSource timeSource; @Subscribe("validateDateBtn") public void onValidateDateBtnClick(Button.ClickEvent event) { Event demoEvent = metadata.create(Event.class); demoEvent.setName("Demo event"); demoEvent.setStartDate(timeSource.currentTimestamp()); demoEvent.setEndDate(DateUtils.addDays(demoEvent.getStartDate(), -1)); ValidationErrors errors = screenValidation.validateCrossFieldRules(this, demoEvent); if (!errors.isEmpty()) { screenValidation.showValidationErrors(this, errors); } } }
-
showUnsavedChangesDialog()
- shows the standard dialog for unsaved changes with Yes and No buttons. It is used in theStandardEditor
. TheshowUnsavedChangesDialog()
method has a handler that responds to user actions. You can see an example of usage in theio.jmix.ui.screen.StandardEditor#preventUnsavedChanges
method. -
showSaveConfirmationDialog()
- shows the standard dialog for confirming saving changed data with Save, Do not save, and Cancel buttons. It is used in theStandardEditor
. TheshowSaveConfirmationDialog()
method has a handler that responds to user actions. You can see an example of usage in theio.jmix.ui.screen.StandardEditor#preventUnsavedChanges
method.You can adjust the dialog type using jmix.ui.screen.use-save-confirmation application property.