SuggestionField 输入提示

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

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

组件的 XML 名称:suggestionField

基本用法

满足下列情况可以使用 SuggestionField

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

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

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

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

suggestion field

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

<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 元素