EntitySuggestionField 实体提示选择

EntitySuggestionField - 实体提示控件 用于根据用户输入的字符串搜索实体实例。当用户点击右侧的按钮时,执行对应的操作。

EntitySuggestionField 是一个输入控件,当用户输入几个字符时,如果能匹配上一些选项,则会展示匹配选项的下拉列表。EntitySuggestionField 在输入每个符号之后刷新选项列表。

选项列表根据应用程序开发者定义的逻辑在后台服务端加载。

事实上,EntitySuggestionFieldSuggestionFieldEntityPicker 的组合。

组件的 XML 名称:entitySuggestionField

基本用法

满足下列情况可以使用 EntitySuggestionField

  • 用户需要选择单一实体实例。

  • 建议值列表的长度对于使用 EntityComboBox 来说太长了。

  • 希望在数据库完成高效搜索,而不是在 UI 层加载太多数据。

entity suggestion field

创建数据感知的 EntitySuggestionField,可以使用 dataContainerproperty XML 属性以及 query 元素:

<data>
    <instance id="addressDc" class="ui.ex1.entity.Address"> (1)
        <fetchPlan extends="_base"> (2)
            <property name="country" fetchPlan="_instance_name"/>
            <property name="city" fetchPlan="_base">
                <property name="country" fetchPlan="_base"/>
            </property>
        </fetchPlan>
    </instance>
</data>
<layout>
    <vbox spacing="true">
        <entitySuggestionField id="countryField"
                               inputPrompt="msg://entitySuggestionField/select"
                               caption="msg://ui.ex1.entity/Address.country"
                               dataContainer="addressDc"
                               property="country">
            <query entityClass="ui.ex1.entity.Country"
                   searchStringFormat="%${searchString}%"
                   escapeValueForLike="true"
                   fetchPlan="_instance_name">
                <![CDATA[select c from uiex1_Country c where lower(c.name)
                like lower(:searchString) escape '\']]>
            </query>
        </entitySuggestionField>
    </vbox>
</layout>
1 InstanceContainer - Address 实体。
2 数据容器内实体的 fetch plan。

界面为具有 country 属性的 Address 实体定义了 id 为 addressDc 的数据容器。在 entitySuggestionField 元素中,通过 dataContainer 属性连接到 addressDc 数据容器,并给 property 属性设置了 country 实体属性。实体属性应该引用另一个实体,在上面的示例中就是 Country 实体。

选项定义

选项列表可以在 XML 描述中用 query 元素定义,或者在控制器中用 SearchExecutor 接口编程式的定义。

query 元素

query 是一个可选的 XML 元素,支持定义查询语句搜索建议值。

query 元素有下列属性:

  • entityClass(必需)- 实体的全限定名称。

  • fetchPlan - 可选属性,指定加载实体所需的 fetch plan。

  • escapeValueForLike - 启用支持搜索包含特殊字符的值:%\ 等。默认值为 false

  • searchStringFormat - Groovy 字符串;可以使用任何有效的 Groovy 表达式。

如需在 Jmix Studio 中添加 query,可以在界面 XML 或者 Component Hierarchy 面板中选择组件,然后点击 Component Inspector 面板的 Add→Query 按钮。

SearchExecutor

如果未定义 query,则需要用 SearchExecutor 编程式设置选项列表。

SearchExecutor 是功能接口,包含单一方法:List<E> search(String searchString, Map<String, Object> searchParams)

searchString 参数是用户输入的字符串,可用于过滤选项。

首先,在 XML 中声明一个组件:

<entitySuggestionField id="entityField"
                       dataContainer="addressDc"
                       property="country"
                       caption="Country"/>

然后为组件设置 SearchExecutor

@Autowired
private DataManager dataManager;

@Install(to = "entityField", subject = "searchExecutor")
private List entityFieldSearchExecutor(String searchString,
                                       Map<String, Object> searchParams) {
    return dataManager.load(Country.class)
            .query("e.name like ?1 order by e.name", "(?i)%" + searchString + "%")
            .list();
}

可以用 Studio 生成 SearchExecutor 实现的桩代码。

search() 方法在后台线程中执行,因此它无法访问可视化组件或数据容器。可直接调用 DataManager 或中间件服务;或处理并返回预先加载到界面的数据。

也可以使用 escapeForLike() 方法来搜索包含特殊符号的值:

@Autowired
private DataManager dataManager;

@Install(to = "entitySuggestionField", subject = "searchExecutor")
private List<Customer> entitySuggestionFieldSearchExecutor(String searchString,
                                                           Map<String, Object> searchParams) {
    searchString = QueryUtils.escapeForLike(searchString);
    return dataManager.load(Customer.class)
            .query("e.firstName like ?1 escape '\\' order by e.firstName", "(?i)%"
                    + searchString + "%")
            .list();
}

metaClass

也可以在不绑定数据容器的情况下使用 EntitySuggestionField,比如,没有设置 dataContainerproperty。此时,需要设置 MetaClass 指定实体类型,示例:

<entitySuggestionField id="metaClassField"
                       metaClass="uiex1_Country"
                       caption="Country"/>

搜索逻辑通过 SearchExecutor 定义:

@Autowired
private DataManager dataManager;

@Install(to = "metaClassField", subject = "searchExecutor")
private List<Country> metaClassFieldSearchExecutor(String searchString,
                                                   Map<String, Object> searchParams) {
    return dataManager.load(Country.class)
            .query("e.name like ?1 order by e.name", "(?i)%" + searchString + "%")
            .list();
}

操作

可以给 EntitySuggestionField 设置自定义或预定义的操作,操作作为按钮显示在右侧。 定义操作可以用 XML 中用内部的 actions 元素或者在控制器中用 addAction() 方法编程式添加。

如需在 Jmix Studio 中添加 action,可以在界面 XML 或者 Component Hierarchy 面板中选择组件,然后点击 Component Inspector 面板的 Add→Action 按钮。

预定义操作

如果创建无操作的 EntitySuggestionField,XML 加载器仅定义 entity_lookupentity_open 操作。还有 entity_clearentity_openComposition 操作。

如需添加其他预定义操作,例如,entity_clear,可以按照下面这样指定 actions 元素:

<entitySuggestionField dataContainer="addressDc"
                       property="country"
                       caption="Country">
    <actions>
        <action id="lookup" type="entity_lookup"/>
        <action id="open" type="entity_open"/>
        <action id="clear" type="entity_clear"/>
    </actions>
</entitySuggestionField>

actions 元素不会扩展但会覆盖一组标准操作。应该明确定义所有必需操作的标识符。

使用 addAction() 以编程方式设置标准操作。如果在组件的 XML 描述中没有内部的 actions 元素,就可以使用这个方法添加缺少的标准操作:

@Autowired
private EntitySuggestionField<Country> entitySuggestionField;

@Autowired
private Actions actions;

@Subscribe
public void onInit(InitEvent event) {
    entitySuggestionField.addAction(actions.create(EntityClearAction.class));
}

自定义操作

EntitySuggestionField 的自定义操作与 EntityPicker自定义操作 类似。

事件和处理器

如需使用 Jmix Studio 生成处理器的桩代码,需要在界面 XML 描述或者 Jmix UI 层级结构面板选中该组件,然后用 Jmix UI 组件面板的 Handlers 标签页生成。

或者可以使用界面控制器顶部面板的 Generate Handler 按钮。

ArrowDownHandler

ArrowDownEvent 当建议值弹窗隐藏且用户按下 向下箭头 时发送。

可以设置自定义的处理方法并使用 EntitySuggestionField.showSuggestions(),该方法接收一组实体作为建议值展示:

@Autowired
private CollectionContainer<Country> countriesDc;

@Autowired
private EntitySuggestionField<Country> countryField;

@Install(to = "countryField", subject = "arrowDownHandler")
private void countryFieldArrowDownHandler(SuggestionFieldComponent.ArrowDownEvent
                                                      arrowDownEvent) {
    countryField.showSuggestions(new ArrayList<>(countriesDc.getItems()));
}

ContextHelpIconClickHandler

EnterPressHandler

参阅 ComboBox 处理用户输入 部分编程式注册的示例。

EnterPressHandler 也可以在界面控制器中使用 @Install 注解声明式的定义。参阅 EntityComboBox 处理用户输入 部分的示例。

FieldIconProvider

参阅 FieldIconProvider

FieldValueChangeEvent

Formatter

为组件添加一个 formatter

下面的例子中,我们展示 cityFieldFormat 实体建议控件 formatter 的用法:

@Install(to = "cityFieldFormat", subject = "formatter")
protected String cityFieldFormatFormatter(City value) {
    return value != null
            ? value.getName() + " (" + (value.getCountry() != null
            ? value.getCountry().getName() : "not defined") + ")"
            : null;
}

如需以编程的方式添加 formatter,使用组件的 addFormatter() 方法。

OptionCaptionProvider

SearchExecutor

参阅 SearchExecutor

Validator

参阅 Validator

ValueChangeEvent

参阅 ValueChangeEvent

EntitySuggestionField XML 元素