3.5.2.1.42. SuggestionField

The SuggestionField component is designed to search for certain values according to a string entered by a user. It differs from SuggestionPickerField in that it can use any types of options: for instance, entities, strings, or enum values, and does not have action buttons. The list of options is loaded in background according to the logic defined by the application developer on the server side.

gui suggestionField 1

XML name of the component: suggestionField.

suggestionField attributes:

  • asyncSearchDelayMs - sets the delay between the last key press action and asynchronous search.

  • minSearchStringLength - sets the minimal string length which is required to perform suggestions search.

  • popupWidth - sets the width of the suggestion popup.

    Possible options:

    • auto - the popup width will be equal to the maximum width of suggestions,

    • parent - the popup width will be equal to the width of main component,

    • absolute (e.g. "170px") or relative (e.g. "50%") value.

  • suggestionsLimit - sets the limit of suggestions to be displayed.

suggestionField elements:

  • query - an optional element which enables defining a query for selecting suggested values. The query element, in turn, has the following attributes:

    • entityClass (required) - full qualified name of entity class.

    • view - optional attribute that specifies the view to be used for loading the queried entity.

    • escapeValueForLike - enables searching for the values that contain special symbols: %, \, etc. Default value is false.

    • searchStringFormat - a Groovy string, thus you can use any valid Groovy-string expressions.

    <suggestionField id="suggestionField"
                     captionProperty="login">
        <query entityClass="com.haulmont.cuba.security.entity.User"
               escapeValueForLike="true"
               view="user.edit"
               searchStringFormat="%$searchString%">
            select e from sec$User e where e.login like :searchString escape '\'
        </query>
    </suggestionField>

    If the query is not defined, the list of options must be provided by SearchExecutor, assigned programmatically (see below).

In the most common case, it is sufficient to set SearchExecutor to the component. SearchExecutor is a functional interface that contains a single method: List<E> search(String searchString, Map<String, Object> searchParams):

suggestionField.setSearchExecutor((searchString, searchParams) -> {
    return Arrays.asList(entity1, entity2, ...);
});

SearchExecutor can return any types of options, for example, entities, strings, or enum values.

  • Entities:

customersDs.refresh();
List<Customer> customers = new ArrayList<>(customersDs.getItems());
suggestionField.setSearchExecutor((searchString, searchParams) ->
        customers.stream()
                .filter(customer -> StringUtils.containsIgnoreCase(customer.getName(), searchString))
                .collect(Collectors.toList()));
  • Strings:

List<String> strings = Arrays.asList("Red", "Green", "Blue", "Cyan", "Magenta", "Yellow");
stringSuggestionField.setSearchExecutor((searchString, searchParams) ->
        strings.stream()
                .filter(str -> StringUtils.containsIgnoreCase(str, searchString))
                .collect(Collectors.toList()));
  • Enum:

List<SendingStatus> enums = Arrays.asList(SendingStatus.values());
enumSuggestionField.setSearchExecutor((searchString, searchParams) ->
        enums.stream()
                .map(sendingStatus -> messages.getMessage(sendingStatus))
                .filter(str -> StringUtils.containsIgnoreCase(str, searchString))
                .collect(Collectors.toList()));
  • OptionWrapper class is used when you need to separate a value of any type and its string representation:

List<OptionWrapper> wrappers = Arrays.asList(
        new OptionWrapper("One", 1),
        new OptionWrapper("Two", 2),
        new OptionWrapper("Three", 3);
suggestionField.setSearchExecutor((searchString, searchParams) ->
        wrappers.stream()
                .filter(optionWrapper -> StringUtils.containsIgnoreCase(optionWrapper.getCaption(), searchString))
                .collect(Collectors.toList()));

The search() method is executed in a background thread so it cannot access visual components or datasources used by visual components. Call DataManager or a middleware service directly; or process and return data loaded to the screen beforehand.

The searchString parameter can be used to filter candidates using the string entered by the user. You can use the escapeForLike() method to search for the values that contain special symbols:

suggestionField.setSearchExecutor((searchString, searchParams) -> {
    searchString = QueryUtils.escapeForLike(searchString);
    return dataManager.loadList(LoadContext.create(Customer.class).setQuery(
            LoadContext.createQuery("select c from sample$Customer c where c.name like :name order by c.name escape '\\'")
                .setParameter("name", "%" + searchString + "%")));
});
  • OptionsStyleProvider enables you to use separate style names for the suggested options displayed by suggestionField:

    suggestionField.setOptionsStyleProvider((field, item) -> {
        User user = (User) item;
        switch (user.getGroup().getName()) {
            case "Company":
                return "company";
            case "Premium":
                return "premium";
            default:
                return "company";
        }
    });