3.5.5.2.13. ViewAction
ViewAction 是 列表操作 设计用来查看和编辑实体实例。与 EditAction 一样,会打开编辑界面,但是所有的字段都是不可编辑的,同时也会禁用那些实现了 Action.DisabledWhenScreenReadOnly
接口的操作。如果需要允许用户切换界面至编辑模式,可以添加一个按钮使用预定义的 enableEditing
操作:
<hbox id="editActions" spacing="true">
<button action="windowCommitAndClose"/>
<button action="windowClose"/>
<button action="enableEditing"/> <!-- 此按钮只会在界面是只读模式时显示 -->
</hbox>
可以在主消息包使用 actions.EnableEditing
键值重定义 enableEditing
操作的标题,或者直接在使用的界面中通过指定相应按钮的 caption
属性进行重定义。
该操作通过 com.haulmont.cuba.gui.actions.list.ViewAction
类实现,在 XML 中需要使用操作属性 type="view"
定义。可以用 action
元素的 XML 属性定义通用的操作参数,参阅 声明式操作 了解细节。下面我们介绍 ViewAction
类特有的参数。
下列参数可以通过 XML 或 Java 的方式设置:
-
openMode
- 编辑界面的打开模式,要求是OpenMode
枚举类型的一个值:NEW_TAB
、DIALOG
等。默认情况下,ViewAction 用THIS_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="com.company.sales.web.customer.CustomerEdit"/>
</properties>
</action>
或者,可以在界面控制器注入该操作,然后用 setter 配置:
@Named("customersTable.view")
private ViewAction customersTableView;
@Subscribe
public void onInit(InitEvent event) {
customersTableView.setOpenMode(OpenMode.DIALOG);
customersTableView.setScreenClass(CustomerEdit.class);
}
现在我们看看那些只能用 Java 代码配置的参数。如果要为这些参数生成带正确注解的方法桩代码,可以用 Studio 中 Component Inspector 工具窗口的 Handlers 标签页功能。
-
screenOptionsSupplier
- 返回ScreenOptions
对象的处理器,返回值可以传递给打开的编辑界面。示例:@Install(to = "customersTable.view", subject = "screenOptionsSupplier") protected ScreenOptions customersTableViewScreenOptionsSupplier() { return new MapScreenOptions(ParamsMap.of("someParameter", 10)); }
返回的
ScreenOptions
对象可以通过打开界面的InitEvent
访问。 -
screenConfigurer
- 接收编辑界面作为参数并能在打开之间初始化界面的处理器。示例:@Install(to = "customersTable.view", subject = "screenConfigurer") protected void customersTableViewScreenConfigurer(Screen editorScreen) { ((CustomerEdit) editorScreen).setSomeParameter(10); }
注意,界面 configurer 会在界面已经初始化但是还未显示时生效,即在界面的
InitEvent
和AfterInitEvent
事件之后,但是在BeforeShowEvent
之前。 -
afterCommitHandler
- 如果用户使用上面提到的enableEditing
操作切换界面至编辑模式时,当实体实例在编辑界面提交之后会被调用的处理器。接收创建的实体作为参数。示例:@Install(to = "customersTable.view", subject = "afterCommitHandler") protected void customersTableViewAfterCommitHandler(Customer entity) { System.out.println("Updated " + entity); }
-
afterCloseHandler
- 在编辑界面关闭后调用的处理器。AfterCloseEvent
事件会传递给该处理器。示例:@Install(to = "customersTable.view", subject = "afterCloseHandler") protected void customersTableViewAfterCloseHandler(AfterCloseEvent event) { if (event.closedWith(StandardOutcome.COMMIT)) { System.out.println("Enabled editing and then committed"); } }
如果需要在该操作执行前做一些检查或者与用户做一些交互,可以订阅操作的 ActionPerformedEvent
事件并按需调用操作的 execute()
方法。操作会使用你为它定义的所有参数进行调用。下面的例子中,我们在执行操作前展示了一个确认对话框:
@Named("customersTable.view")
private ViewAction customersTableView;
@Subscribe("customersTable.view")
public void onCustomersTableView(Action.ActionPerformedEvent event) {
dialogs.createOptionDialog()
.withCaption("Please confirm")
.withMessage("Do you really want to view the customer?")
.withActions(
new DialogAction(DialogAction.Type.YES)
.withHandler(e -> customersTableView.execute()), // execute action
new DialogAction(DialogAction.Type.NO)
)
.show();
}
另外,还可以先订阅 ActionPerformedEvent
,但是不调用操作的 execute()
方法,而是使用 ScreenBuilders
API 直接打开编辑界面。此时,会忽略所有的操作参数和行为,只能用其通用参数,比如 caption, icon 等。示例:
@Inject
private ScreenBuilders screenBuilders;
@Subscribe("customersTable.view")
public void onCustomersTableView(Action.ActionPerformedEvent event) {
CustomerEdit customerEdit = screenBuilders.editor(customersTable)
.withOpenMode(OpenMode.DIALOG)
.withScreenClass(CustomerEdit.class)
.withAfterCloseListener(afterScreenCloseEvent -> {
if (afterScreenCloseEvent.closedWith(StandardOutcome.COMMIT)) {
Customer committedCustomer = (afterScreenCloseEvent.getScreen()).getEditedEntity();
System.out.println("Updated " + committedCustomer);
}
})
.build();
customerEdit.setReadOnly(true);
customerEdit.show();
}