entityComboBox 实体下拉框
支持用户从下拉列表中选择单一 实体 实例并进行相关操作。操作可以是预定义的操作,例如更新实例的详细信息,或自定义的操作以完成其他一些任务。
事实上,entityComboBox
是 comboBox 和 entityPicker 的组合。
-
XML 元素:
entityComboBox
-
Java 类:
EntityComboBox
基本用法
当字段值是实体对象时,通常使用 entityComboBox
组件。支持用户选择特定实体实例并执行相关操作。
点击控件或箭头按钮可以打开一个显示实体实例的下拉框:
请注意,除非您配置了懒加载,否则该组件会将选项中所有实例的列表加载到浏览器的内存和服务器的内存中。这可能会消耗更多系统资源,特别是加载大量选项时,甚至会影响性能。此外,选项过多也会让用户难以找到特定的实例。
如果选项过多,例如几千或更多,又或者在选择实例时需要提供更多的信息,那么建议使用 entityPicker。 |
简单用例
下面的示例演示如何使用 entityCombobox
组件选择用户所属的部门:
<data>
<instance class="com.company.onboarding.entity.User"
id="userDc"> (1)
<fetchPlan extends="_base"> (2)
<property name="department" fetchPlan="_base"/>
</fetchPlan>
<loader id="userDl"/>
</instance>
<collection class="com.company.onboarding.entity.Department"
id="departmentsDc"> (3)
<fetchPlan extends="_base"/>
<loader id="departmentsDl">
<query>
<![CDATA[select e from Department e]]>
</query>
</loader>
</collection>
</data>
<facets>
<dataLoadCoordinator auto="true"/> (4)
</facets>
<layout>
<entityComboBox dataContainer="userDc"
property="department"
itemsContainer="departmentsDc"> (5)
<actions>
<action id="entityClear" type="entity_clear"/> (6)
</actions>
</entityComboBox>
</layout>
1 | 保存当前正在编辑的 User 实例的数据容器。 |
2 | 扩展了 fetch plan,以获取 Department 实例集合作为选项。 |
3 | 保存所有现有 Department 实例集合的数据容器。 |
4 | 数据加载协调器,自动为组件提供实例选项。 |
5 | 将组件与数据容器和属性绑定。指定选项列表的容器。 |
6 | 添加预定义操作,用于清除所选内容。 |
有关 entityComboBox
及其变体的更多交互式示例,请参阅:
数据绑定
数据绑定是指将组件与数据容器进行关联。可视化组件或相应数据容器中的更改可以触发彼此的更新。有关详细信息,请参阅 使用数据组件。
选择一个实例
如果只是简单的需要选择一个实体实例,那么可以通过 metaClass
属性指定实体。如果需要从一组特定的实体实例中选择,则可以通过 itemsContainer 属性指定。
<entityComboBox metaClass="Department"
itemsContainer="departmentsDc">
// ...
</entityComboBox>
更新关联属性
选择实体实例通常用来更新另一个实体中的一个属性。在 上面的示例 中,通过选择 Department
实例更新了 User
实例中的部门属性。
此时,需要将组件绑定至父实体的数据容器,并指定需要更新的属性,这两个步骤分别通过 dataContainer 和 property 属性实现。通过 itemsContainer 属性指定选项列表。
<entityComboBox dataContainer="userDc"
property="department"
itemsContainer="departmentsDc">
// ...
</entityComboBox>
操作
entityComboBox
初始化时并不带任何操作,需要显式地添加,示例:
<entityComboBox dataContainer="userDc"
property="department"
itemsContainer="departmentsDc">
<actions>
<action id="entityClear" type="entity_clear"/>
<action id="entityLookup" type="entity_lookup"/>
<action id="entityOpen" type="entity_open"/>
</actions>
</entityComboBox>
如需在 Jmix Studio 中添加 |
自定义和预定义操作的详细信息请参阅 entityPicker
的 操作 部分。
延迟加载
该组件支持根据用户输入批量加载选项,而不是一次加载全部选项。这样可以确保流畅的用户体验,即便选项数量非常庞大。
声明式配置
若要在视图 XML 中实现延迟加载,需要配置 itemsQuery
属性,而不是 itemsContainer
。例如,要最多加载 30 个选项并在列表中显示,可按照下列代码:
<entityComboBox metaClass="Department" pageSize="30"> (1)
<itemsQuery class="com.company.onboarding.entity.User"
searchStringFormat="(?i)%${inputString}%"
escapeValueForLike="true"
fetchPlan="_instance_name"> (2)
<query>
<![CDATA[select e from Department e where e.name like :searchString order by e.name]]> (3)
</query>
</itemsQuery>
</entityComboBox>
1 | pageSize 属性定义每次批量加载的数据量。默认为 50。 |
2 | itemsQuery 中的属性可以控制加载的过程。解释如下:
|
3 | JPQL 查询语句。 |
编程式配置
选项的加载过程也可以通过代码在 itemsFetchCallback
处理方法中配置。示例:
<entityComboBox id="departmentComboBox" metaClass="Department"/>
@ViewComponent
private EntityComboBox<Department> departmentField;
@Install(to = "departmentComboBox", subject = "itemsFetchCallback")
private Stream<Department> departmentFieldItemsFetchCallback(final Query<Department, String> query) {
String param = query.getFilter().orElse("");
return dataManager.load(Department.class)
.condition(PropertyCondition.contains("name", param))
.firstResult(query.getOffset())
.maxResults(query.getLimit())
.list()
.stream();
}
示例中,数据通过 DataManager 获取,但是也可以修改为通过自定义服务获取。
自定义渲染器
默认情况下,下拉框中的实体实例是以纯文本进行显示。可以自定义渲染器,实现下拉框选项的渲染逻辑,比如可以包含组件、图标、甚至布局。
例如,定义下面的渲染器在部门名称前添加一个图标:
@Supply(to = "customRendererField", subject = "renderer")
private Renderer<Department> departmentRenderer() {
return new ComponentRenderer<>(department -> {
Icon icon = VaadinIcon.USERS.create();
HorizontalLayout contentBox = uiComponents.create(HorizontalLayout.class);
contentBox.setPadding(false);
contentBox.add(icon);
contentBox.add(department.getName());
return contentBox;
});
}
XML 属性
id - alignSelf - allowCustomValue - ariaLabel - ariaLabelledBy - allowedCharPattern - autoOpen - autofocus - classNames - colspan - css - dataContainer - enabled - errorMessage - focusShortcut - height - helperText - itemsContainer - label - maxHeight - maxWidth - metaClass - minHeight - minWidth - opened - overlayClass - pageSize - pattern - placeholder - property - readOnly - required - requiredMessage - tabIndex - themeNames - title - visible - width
allowCustomValue
如果 allowCustomValue
属性为 true
,用户可以输入不匹配任何选项的字符串值,此时会触发 CustomValueSetEvent。
注意,entityComboBox
不会自动处理自定义字符串。请使用 CustomValueSetEvent
进行处理。
默认值为 false
。
itemsContainer
设置包含选项列表的数据容器名称。组件将实体的 实例名 作为选项展示。
事件和处理器
AttachEvent - BlurEvent - ComponentValueChangeEvent - CustomValueSetEvent - DetachEvent - FocusEvent - itemLabelGenerator - statusChangeHandler - validator - renderer
在 Jmix Studio 生成处理器桩代码时,可以使用 Jmix UI 组件面板的 Handlers 标签页或者视图类顶部面板的 Generate Handler 添加,也可以通过 Code → Generate 菜单(Alt+Insert / Cmd+N)生成。 |
CustomValueSetEvent
当用户输入非空值,且不匹配任何已有选项时,发出 com.vaadin.flow.component.combobox.ComboBoxBase.CustomValueSetEvent
事件。如需启用自定义输入,请设置 allowCustomValue 属性为 true
。
<entityComboBox dataContainer="userDc"
property="department"
itemsContainer="departmentsDc"
id="departmentField"
allowCustomValue="true"/>
@ViewComponent
private CollectionContainer<Department> departmentsDc;
@ViewComponent
private EntityComboBox<Department> departmentField;
@Autowired
private DataManager dataManager;
@Subscribe("departmentField")
public void onDepartmentFieldCustomValueSet(ComboBoxBase.CustomValueSetEvent
<ComboBox<Department>> event) {
Department department = dataManager.create(Department.class); (1)
department.setName(event.getDetail()); (2)
departmentsDc.getMutableItems().add(department); (3)
departmentField.setValue(department);
}
1 | 创建一个新实例合并至上下文。 |
2 | 为新创建的 department 实体设置名称。 |
3 | 添加合并的实体。 |
XML 内部元素
actions - itemsQuery - prefix - tooltip - validator