Валидация с учетом групп ограничений в визуальных компонентах

Здравствуйте!

Jmix version: 2.2.1.
Возникла необходимость валидации в визуальных компонентах с учетом групп ограничений, но не понятно пока как лучше это организовать. Например, у компонента TypedTextField есть метод executeValidators(), который запустит валидацию с группами Default.class, UiComponentChecks.class, но нет что-то подобного executeValidators(Class<?>… groups). Судя по документации, в прошлых версиях платформы можно было взять все валидаторы компонента, добраться до BeanPropertyValidator и работать с ним:

field2.getValidators().stream()
               .filter(BeanPropertyValidator.class::isInstance)
               .forEach(validator -> {
                   ((BeanPropertyValidator) validator).setValidationGroups(new Class[] {UiComponentChecks.class}); 
               });

но в Jmix 2.2.1 getValidators() нет, только getDefaultValidator().

Каким образом запустить программно валидацию этого компонента с учетом собственной группы?

Добрый день.

С технической точки зрения, визуальным компонентам все равно на группу ограничений, т.к. при вызове метода executeValidators() выполняются все добавленные в компонент валидаторы.

При сохранении сущности в экране редактирования вызывается метод бина ViewValidation#validateUiComponents, который пробегается по UI компонентам и вызывает их метод executeValidators().


Группы ограничений применяются при валидации объектов, например сущности. Для этого используется jakarta.validation.Validator, например:

@Autowired
private Validator validator;

@Subscribe(id = "performBeanValidationBtn", subject = "clickListener")
public void onPerformBeanValidationBtnClick(final ClickEvent<JmixButton> event) {
    Set<ConstraintViolation<Project>> violations = validator.validate(getEditedEntity(),
            Default.class, UiComponentChecks.class, UiCrossFieldChecks.class);

    // handle violations
}

Так же этому бину делегирует свою работу io.jmix.flowui.view.ViewValidation#validateBeanGroup, который, например, используется для проверки UiCrossFieldChecks.class.


Да, в данный момент, такой метод отсутствует. Если действительно необходимо добавить группу в инстанст Бин Валидатора, добавляемого визуальному компоненту, то можно переопределить
io.jmix.flowui.component.validation.bean.BeanPropertyValidator и его метод accept, т.к. в нем, если при создании бина не были явно указаны группы, то добавляются дефолтные.


Если Вы поподробнее опишите саму задачу, то, возможно, я могу посоветовать Jmix решение.

С уважением,
Глеб

1 симпатия

Добрый день!

Глеб, спасибо за развернутый ответ, попробую описать подробнее. Имеется экран StandardDetailView<T>, редактируемая сущность <T> которого по сути является документом. Документ большой, поэтому пользователь может заполнять его не за один раз. На этапе заполнения он может его сохранять как черновик, в этом случае одни ограничения или отправить на согласование, где добавляются дополнительные проверки (обязательность заполнения полей и пр.). Поведение UI компонентов при нарушении ограничений в обоих случаях должно быть одинаковым, то есть подсвечиваться красным цветом.

Я могу сделать тестовый проект-пример и залить на GitHub, если это поможет.

С уважением, Павел

тут можно просто вызывать setRequired(true) для конкретных компонентов на момент открытия экрана

Прочие проверки добавлять через addValidator

Учитывая, что некоторые проверки зависят от состояния сущности в целом, можно подписаться на ValidationEvent (пример есть в UserDetailView для валидации совпадения паролей).

С точки зрения кода, такое подход будет читабельнее и понятнее, чем пытаться отключать ValidationGroups.

Глеб