AddAction

AddAction – это действие с коллекцией, предназначенное для добавления существующих экземпляров сущности из экрана выбора в контейнер данных. Например, оно используется для заполнения many-to-many коллекций.

Действие реализовано классом io.jmix.ui.action.list.AddAction и объявляется в XML с помощью атрибута type="add". Общие свойства действий можно конфигурировать с помощью атрибутов элемента action, подробнее см. раздел Декларативное создание действий. Ниже рассматриваются параметры, специфичные для класса AddAction.

Параметры

Следующие параметры можно установить и в XML, и в Java:

  • openMode - режим открытия экрана выбора, задаваемый значением перечисления OpenMode: NEW_TAB, DIALOG, и т.д. По умолчанию AddAction открывает экран выбора в режиме THIS_TAB.

  • screenId - строковый идентификатор экрана выбора. По умолчанию AddAction использует экран, аннотированный @PrimaryLookupScreen, или имеющий идентификатор вида <entity_name>.browse, например demo_Order.browse.

  • screenClass - класс Java экрана выбора. Данный параметр имеет более высокий приоритет, чем screenId.

Например, если необходимо открыть определенный экран выбора в режиме диалога, действие можно сконфигурировать в XML следующим образом:

<action id="add" type="add">
    <properties>
        <property name="openMode" value="DIALOG"/>
        <property name="screenClass" value="ui.ex1.screen.entity.brand.BrandBrowse"/>
    </properties>
</action>

В качестве альтернативы, действие можно инжектировать в контроллер экрана и сконфигурировать, используя сеттеры:

@Named("brandsTable.add")
private AddAction<Brand> addAction;

@Subscribe
public void onInitEntity(InitEntityEvent<Customer> event) {
    addAction.setOpenMode(OpenMode.DIALOG);
    addAction.setScreenClass(BrandBrowse.class);
}

Обработчики

Далее рассматриваются параметры, которые можно сконфигурировать только программно в Java. Для генерации корректно аннотированных методов для этих параметров используйте use Studio.

screenOptionsSupplier

Это обработчик, возвращающий объект ScreenOptions для передачи в открываемый экран выбора. Например:

@Install(to = "brandsTable.add", subject = "screenOptionsSupplier")
private ScreenOptions brandsTableAddScreenOptionsSupplier() {
    return new MapScreenOptions(ParamsMap.of("someParameter", 10));
}

Возвращаемый объект ScreenOptions будет доступен в InitEvent открываемого экрана.

screenConfigurer

Это обработчик, принимающий экран выбора для его конфигурации перед открытием. Например:

@Install(to = "brandsTable.add", subject = "screenConfigurer")
private void brandsTableAddScreenConfigurer(Screen screen) {
    ((BrandBrowse) screen).setSomeParameter(10);
}

Обратите внимание, что конфигуратор экрана вступает в действие, когда экран уже инициализирован, но еще не показан, то есть после InitEvent и AfterInitEvent, и до BeforeShowEvent.

selectValidator

Это обработчик, вызываемый когда пользователь нажимает Select в экране выбора. Он принимает объект, содержащий выбранные сущности. Данный обработчик можно использовать для проверки выбора по каким-либо критериям. Обработчик должен вернуть true для того, чтобы процесс был продолжен и экран выбора закрылся. Например:

@Install(to = "brandsTable.add", subject = "selectValidator")
private boolean brandsTableAddSelectValidator(LookupScreen.ValidationContext<Brand> validationContext) {
    boolean valid = checkBrands(validationContext.getSelectedItems());
    if (!valid) {
        notifications.create().withCaption("Selection is not valid").show();
    }
    return valid;
}

transformation

Это обработчик, вызываемый после того, как сущность выбрана и прошла валидацию в экране редактирования. Он принимает выбранную сущность и может быть использован для того, чтобы преобразовать закоммиченную сущность перед ее установкой в целевой контейнер данных. Например:

@Install(to = "brandsTable.add", subject = "transformation")
private Collection<Brand> brandsTableAddTransformation(Collection<Brand> collection) {
    return reloadBrands(collection);
}

afterCloseHandler

Это обработчик, вызываемый после закрытия экрана выбора. Принимает AfterCloseEvent. Например:

@Install(to = "brandsTable.add", subject = "afterCloseHandler")
private void brandsTableAddAfterCloseHandler(AfterCloseEvent afterCloseEvent) {
    if (afterCloseEvent.closedWith(StandardOutcome.SELECT)) {
        System.out.println("Selected");
    }
}

Использование ActionPerformedEvent

Для того чтобы произвести какие-либо проверки, или взаимодействовать с пользователем перед выполнением действия, необходимо подписаться на событие ActionPerformedEvent действия и в нужный момент вызвать метод execute(). Действие будет вызвано со всеми параметрами, которые были для него заданы. В примере ниже перед выполнением действия отображается диалог подтверждения:

@Subscribe("brandsTable.add")
public void onBrandsTableAdd(Action.ActionPerformedEvent event) {
    dialogs.createOptionDialog()
            .withCaption("Please confirm")
            .withMessage("Do you really want to add a brand?")
            .withActions(
                    new DialogAction(DialogAction.Type.YES)
                            .withHandler(e -> addAction.execute()), // execute action
                    new DialogAction(DialogAction.Type.NO)
            )
            .show();
}

Можно также подписаться на ActionPerformedEvent, и вместо вызова метода execute() действия, использовать для открытия экрана выбора ScreenBuilders API напрямую. По сути, в этом случае все специфичные параметры действия игнорируются, и действуют только общие параметры: caption, icon, и т.д. Например:

@Subscribe("brandsTable.addAction")
public void onBrandsTableAddAction(Action.ActionPerformedEvent event) {
    screenBuilders.lookup(brandsTable)
            .withOpenMode(OpenMode.DIALOG)
            .withScreenClass(BrandBrowse.class)
            .withSelectValidator(customerValidationContext -> {
                boolean valid = checkBrands(customerValidationContext.getSelectedItems());
                if (!valid) {
                    notifications.create().withCaption("Selection is not valid").show();
                }
                return valid;

            })
            .build()
            .show();
}