SuggestionField 输入提示

SuggestionField - 输入提示 组件用于根据用户输入的字符串搜索一些值。

它可以使用任何类型的选项:实体、字符串或枚举值,SuggestionField 没有操作按钮。选项列表是根据应用程序开发人员定义的逻辑在后端加载。

组件的 XML 名称:suggestionField。

基本用法

满足下列情况可以使用 SuggestionField:

  • 用户需要选择单一选项。

  • 提示值列表的长度对于使用 ComboBox 或 EntityComboBox 来说太长了。

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

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

suggestion field

如需创建关联至数据的 SuggestionField,可以用 XML 的 dataContainer 和 property 属性:

<data>
    <instance id="addressDc" class="ui.ex1.entity.Address"> (1)
        <fetchPlan extends="_base"> (2)
            <property name="country" fetchPlan="_instance_name"/>
        </fetchPlan>
    </instance>
</data>
<layout>
    <suggestionField id="countryField"
                     dataContainer="addressDc"
                     property="country"
                     caption="Country"
                     inputPrompt="Start typing the country name">
    </suggestionField>
</layout>
1 InstanceContainer - Address 实体。
2 数据容器内实体的 fetch plan。

如需启用 SuggestionField 提示功能,需要使用 search executor,示例:

@Autowired
private DataManager dataManager;

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

SearchExecutor

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

使用 searchString 参数(用户输入的字符串)对选项进行过滤。

大部分情况下,给组件设置一个 SearchExecutor 的实现就足够了。

SearchExecutor 可以返回任何类型的选项,例如实体、字符串或枚举值。

  • 实体

    首先,在 XML 中定义组件:

    <suggestionField id="entityField" visible="false"
                     caption="msg://suggestionfield/entitySuggestion"
                     inputPrompt="Start typing the country name"/>

    然后,为组件设置 SearchExecutor:

    @Autowired
    private DataManager dataManager;
    
    
    @Install(to = "entityField", subject = "searchExecutor")
    private List<Country> 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 实现的桩代码。

  • 字符串

    @Install(to = "stringField", subject = "searchExecutor")
    private List stringFieldSearchExecutor(String searchString,
                                           Map<String, Object> searchParams) {
        return Stream.of("John", "Andy", "Dora", "Martin", "Peter", "George")
                .filter(str -> StringUtils.containsIgnoreCase(str, searchString))
                .collect(Collectors.toList());
    }
  • 枚举

    @Autowired
    private Messages messages;
    
    @Install(to = "enumField", subject = "searchExecutor")
    private List enumFieldSearchExecutor(String searchString,
                                         Map<String, Object> searchParams) {
        return Stream.of(Hobby.values())
                .filter(status ->
                        StringUtils.containsIgnoreCase(messages.getMessage(status),
                                searchString))
                .collect(Collectors.toList());
    }

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

escapeForLike

也可以使用 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();
}

Suggestions Managing

asyncSearchDelayMs

asyncSearchDelayMs 属性设置最后一次按键操作和执行异步搜索之前需要的延迟。

minSearchStringLength

minSearchStringLength 属性设置执行提示搜索需要的最小字符串长度。

如果设置 minSearchStringLength = 1,提示弹窗会在用户开始输入时立即弹出,并且第一次会展示太多提示选项。如果是从大量的数据中搜索,请降低 SuggestionField 的阈值,示例:

minSearchStringLength="4"

popupWidth 属性设置提示弹窗的宽度。可能值:

  • auto - 弹窗宽度等于提示选项中的最大宽度。

  • parent - 弹窗宽度等于主组件的宽度。

  • 绝对(例如,"170px")或相对(例如,"50%")值。

suggestionsLimit

suggestionsLimit 属性设置展示提示选项的个数。默认值为 10。

事件和处理器

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

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

ArrowDownHandler

ContextHelpIconClickHandler

EnterPressHandler

参考 ComboBox 的 处理用户输入 章节示例,如何以编程的方式进行注册。

EnterPressHandler 也可以在界面控制器用 @Install 注解声明式的注册。参考 EntityComboBox 的 处理用户输入 章节的示例。

Formatter

参阅 Formatter。

OptionsStyleProvider

OptionsStyleProvider 可以管理提示选项弹窗的附加样式名:

@Install(to = "customerSuggestionField", subject = "optionStyleProvider")
private String customerSuggestionFieldOptionStyleProvider(Customer customer) {
    if (customer != null) {
        switch (customer.getLevel()) {
            case SILVER:
                return "silver-level";
            case GOLD:
                return "gold-level";
            case PLATINUM:
                return "platinum-level";
            case DIAMOND:
                return "diamond-level";
        }
    }
    return null;
}

然后可以在应用程序主题中定义各种样式。创建主题的详细信息参阅 主题。样式名在控制器中提供,加上标识每个选项的前缀,形成 CSS 选择器,示例:

.silver-level {
    background-color: #c0c0c0;
    color: black;
}

.gold-level {
    background-color: #fdd017;
    color: black;
}

.platinum-level {
    background-color: #e5e4e2;
    color: black;
}

.diamond-level {
    background-color: #b9f2ff;
    color: black;
}
suggestion field styles

SearchExecutor

参阅 SearchExecutor。

Validator

参阅 Validator。

ValueChangeEvent

参阅 ValueChangeEvent。

SuggestionField XML 元素