Fragments
一个 fragment 是一个 UI 块,可以作为视图的一部分或其他 fragment 的一部分使用。由不同的 UI 组件构成,但是还提供了下列附加功能:
-
可以在 XML 中定义内容。
-
视图和其他 fragment 中可以用
fragment
XML 元素声明式引入 fragment。 -
Fragment 类(也称控制器)中可以注入 Spring bean 或 fragment 的 UI 组件,并能使用带注解的方法作为事件处理方法。
-
ReadyEvent
在 fragment 初始化完成时发送。 -
Fragment 的 XML 中可以定义 操作 和 数据组件(数据容器或加载器)。数据组件可以标记为
provided
,表示由父视图提供。 -
Studio 提供了 Blank fragment 模板可以生成空的 fragment,然后在 Jmix 工具窗口展示,与视图一样,也可以使用 可视化设计器。
Fragments 目前不支持 facets。
Fragment 内容
@FragmentDescriptor
注解可以设置一个字符串值,表示用于初始化 fragment 的 XML 路径。如果该值仅设置了文件名(并且不以 /
开头),则假定文件位于 fragment 类的同名包中。
XML 中可设置的元素:
-
content
- 必需元素,设置 fragment 的布局(是视图的layout
元素类似)。由于 fragment 的根组件可以是任何组件,因此content
没有属性,也不表示任何组件。 -
actions
- 可选元素,设置 fragment 内的操作(与视图的actions
元素类似)。如果操作有快捷键,则将与片段的根组件绑定。也就是说,只有当焦点位于片段布局内时,才能触发快捷键。 -
data
- 可选元素,设置 fragment 内的数据(与视图的data
元素类似)。fragment 可以定义自己的数据容器和加载器,也可以通过 id 从父视图或 fragment 中获取,参阅 使用数据组件 部分。
Fragment 的 XML 示例:
<fragment xmlns="http://jmix.io/schema/flowui/fragment">
<data>
<collection id="customersDc"
class="com.company.onboarding.entity.Customer">
<fetchPlan extends="_base">
<property name="city" fetchPlan="_base"/>
</fetchPlan>
<loader id="customersDl" readOnly="true">
<query>
<![CDATA[select e from Customer e]]>
</query>
</loader>
</collection>
</data>
<content>
<vbox id="root" padding="false">
<genericFilter id="genericFilter"
dataLoader="customersDl">
<properties include=".*"/>
</genericFilter>
<hbox id="buttonsPanel" classNames="buttons-panel">
<button id="createBtn" action="customersDataGrid.create"/>
<button id="editBtn" action="customersDataGrid.edit"/>
<button id="removeBtn" action="customersDataGrid.remove"/>
<simplePagination id="pagination" dataLoader="customersDl"/>
</hbox>
<dataGrid id="customersDataGrid"
width="100%"
minHeight="20em"
dataContainer="customersDc"
columnReorderingAllowed="true">
<actions>
<action id="create" type="list_create"/>
<action id="edit" type="list_edit"/>
<action id="remove" type="list_remove"/>
</actions>
<columns resizable="true">
<column property="city"/>
<column property="level"/>
<column property="age"/>
<column property="martialStatus"/>
<column property="hobby"/>
<column property="firstName"/>
<column property="lastName"/>
<column property="email"/>
<column property="rewardPoints"/>
</columns>
</dataGrid>
</vbox>
</content>
</fragment>
Fragment API
-
getFragmentData()
- 返回FragmentData
对象,该对象的方法可以与 fragment 的数据组件交互。 -
getFragmentActions()
- 返回FragmentActions
对象,该对象的方法可以与 fragment 的操作交互。与ViewActions
类似。 -
getParentController()
- 返回FragmentOwner
父对象。父对象可能是View
或Fragment
。 -
findInnerComponent()
/getInnerComponent()
- 返回给定 id 的内部组件。该方法仅搜索通过 XML 添加的内部组件。
Fragment 事件
-
ReadyEvent
- 在 fragment 及所有声明式定义的内部组件创建并初始化完成后触发的事件。在此事件监听器中,可以对 fragment 及其内部组件进行最终配置。示例:CustomerListFragment.java@FragmentDescriptor("customer-list-fragment.xml") public class CustomerListFragment extends Fragment<VerticalLayout> { @Subscribe public void onReady(final ReadyEvent event) { getFragmentData().loadAll(); (1) } }
1 触发 fragment 中注册的所有加载器(包括 provided)的 load()
方法。
注入
与视图一样,fragment 也支持注入 XML 中定义的组件或调用带注解的事件处理方法:
@ViewComponent
public JmixButton button; (1)
@ViewComponent
public CollectionContainer<Customer> collectionDc; (2)
@Subscribe
public void onReady(ReadyEvent event) { (3)
// ...
}
@Subscribe(value = "button", subject = "clickListener")
public void onButtonClick(ClickEvent<JmixButton> event) { (4)
// ...
}
@Install(to = "collectionDl", target = Target.DATA_LOADER)
public List<Customer> collectionDlLoadDelegate(LoadContext<Customer> loadContext) { (5)
return loadCustomers(loadContext);
}
@Supply(to = "dataGrid.name", subject = "renderer")
public Renderer<Customer> dataGridNameRenderer() { (6)
return createRenderer();
}
1 | 注入一个 UI 组件。 |
2 | 注入一个数据容器。 |
3 | 订阅 fragment 的 ReadyEvent 事件。 |
4 | 订阅一个按钮的 ClickEvent 事件。 |
5 | 安装加载器代理。 |
6 | 为数据表格提供一个 Renderer 。 |
此外,还可以订阅父视图的事件。在 @Subscribe
注解中定义 target = Target.HOST_CONTROLLER
:
@Subscribe(target = Target.HOST_CONTROLLER)
public void onHostInit(View.InitEvent event) {
// ...
}
@Subscribe(target = Target.HOST_CONTROLLER)
public void onHostBeforeShow(View.BeforeShowEvent event) {
// ...
}
@Subscribe(target = Target.HOST_CONTROLLER)
public void onHostReady(View.ReadyEvent event) {
// ...
}