查看

ViewAction 是一个 列表操作,用来查看和编辑实体实例。与 EditAction 一样打开实体编辑界面,但是所有的字段都是不可编辑的,同时也会禁用提交数据的操作。如果需要允许用户切换界面至编辑模式,可以添加一个用预定义的 enableEditing 操作的按钮:

<hbox id="editActions" spacing="true">
    <button id="commitAndCloseBtn" action="windowCommitAndClose"/>
    <button id="closeBtn" action="windowClose"/>
    <button action="enableEditing"/> (1)
</hbox>
1 此按钮只会在界面是只读模式时显示。

可以在主消息包使用 actions.EnableEditing 键值重定义 enableEditing 操作的标题,或者直接在使用的界面中通过指定相应按钮的 caption 属性进行重定义。

界面需要实现 ReadOnlyAwareScreen 接口才能使用该操作和 enableEditing 操作。StandardEditor 已经实现了这个接口。

该操作通过 io.jmix.ui.action.list.ViewAction 类实现,在 XML 中需要使用操作属性 type="view" 定义。可以用 action 元素的 XML 属性定义通用的操作参数,参阅 声明式操作 了解细节。下面我们介绍 ViewAction 类特有的参数。

属性

下列参数可以在 XML 或 Java 中设置:

  • openMode - 编辑界面的打开模式,是 OpenMode 枚举类型值:NEW_TABDIALOG 等。默认情况下,ViewActionTHIS_TAB 模式打开编辑界面。

  • screenId - 编辑界面的字符串 id。ViewAction 默认会使用带有 @PrimaryEditorScreen 注解的界面,或标识符为 <entity_name>.edit 格式的界面,例如,demo_Customer.edit

  • screenClass - 编辑界面控制器的 Java 类。比 screenId 有更高的优先级。

示例,需要以对话框方式打开一个特定的编辑界面,可以在 XML 中这样配置操作:

<action id="view" type="view">
    <properties>
        <property name="openMode" value="DIALOG"/>
        <property name="screenClass" value="ui.ex1.screen.entity.customer.CustomerEdit"/>
    </properties>
</action>

或者,可以在界面控制器注入该操作,然后用 setter 配置:

@Named("custTable.view")
private ViewAction<Customer> viewAction;

@Subscribe
public void onInit(InitEvent event) {
    viewAction.setOpenMode(OpenMode.DIALOG);
    viewAction.setScreenClass(CustomerEdit.class);
}

处理器

下面了解这些只能用 Java 配置的参数。用 Studio 能为这些参数正确生成带注解的方法。

screenOptionsSupplier

返回 ScreenOptions 对象,返回值可以传递给打开的编辑界面。示例:

@Install(to = "custTable.view", subject = "screenOptionsSupplier")
private ScreenOptions custTableViewScreenOptionsSupplier() {
    return new MapScreenOptions(ParamsMap.of("someParameter", 10));
}

返回的 ScreenOptions 对象可以在打开界面的 InitEvent 中使用。

screenConfigurer

接收编辑界面作为参数并能在打开之前初始化界面。示例:

@Install(to = "custTable.view", subject = "screenConfigurer")
private void custTableViewScreenConfigurer(Screen screen) {
    ((CustomerEdit) screen).setSomeParameter(10);
}

注意,界面 configurer 会在界面已经初始化但是还未显示时生效,即在界面的 InitEventAfterInitEvent 事件之后,但是在 BeforeShowEvent 之前。

transformation

在编辑界面选择实体并验证之后调用。接收选中的实体作为参数。可以用这个处理器对选中的实体做一些处理(如果执行了 enableEditing 操作),然后再传递给接收的数据容器。示例:

@Install(to = "custTable.view", subject = "transformation")
private Customer custTableViewTransformation(Customer customer) {
    return reloadCustomer(customer);
}

afterCommitHandler

如果用户通过上面提到的 enableEditing 操作将界面切换成编辑模式,当实体实例在编辑界面提交之后会调用。接收更新的实体作为参数。示例:

@Install(to = "custTable.view", subject = "afterCommitHandler")
private void custTableViewAfterCommitHandler(Customer customer) {
    System.out.println("Updated " + customer);
}

afterCloseHandler

在编辑界面关闭后调用。AfterCloseEvent 事件会传递给该处理器。示例:

@Install(to = "custTable.view", subject = "afterCloseHandler")
private void custTableViewAfterCloseHandler(AfterCloseEvent afterCloseEvent) {
    if (afterCloseEvent.closedWith(StandardOutcome.COMMIT)) {
        System.out.println("Enabled editing and then committed");
    }
}

使用 ActionPerformedEvent

如果需要在该操作执行前做一些检查或者与用户做一些交互,可以订阅操作的 ActionPerformedEvent 事件并按需调用操作的 execute() 方法。操作会使用你为它定义的所有参数进行调用。下面的例子中,我们在执行操作前展示了一个确认对话框:

@Autowired
private ScreenBuilders screenBuilders;

@Subscribe("custTable.view")
public void onCustTableView(Action.ActionPerformedEvent event) {
    CustomerEdit customerEdit = screenBuilders.editor(custTable)
            .withOpenMode(OpenMode.DIALOG)
            .withScreenClass(CustomerEdit.class)
            .withAfterCloseListener(afterScreenCloseEvent -> {
                if (afterScreenCloseEvent.closedWith(StandardOutcome.COMMIT)) {
                    Customer committedCustomer = (afterScreenCloseEvent.getSource()).getEditedEntity();
                    System.out.println("Updated " + committedCustomer);
                }
            })
            .build();
    customerEdit.setReadOnly(true);
    customerEdit.show();
}