5.5.2.1.23. LookupField

Компонент для выбора значения из выпадающего списка. Выпадающий список реализует фильтрацию значений по мере ввода пользователя и постраничный вывод доступных значений.

gui lookupField

XML-имя компонента: lookupField.

Компонент LookupField реализован для блоков Web Client и Desktop Client.

  1. Простейший вариант использования LookupField - выбор значения перечисления (enum) для атрибута сущности. Например, сущность Role имеет атрибут type типа RoleType, который является перечислением. Тогда для редактирования этого атрибута можно использовать LookupField следующим образом:

    <dsContext>
        <datasource id="roleDs" class="com.haulmont.cuba.security.entity.Role" view="_local"/>
    </dsContext>
    <layout>
        <lookupField datasource="roleDs" property="type"/>

    Как видно из примера, в экране описывается источник данных roleDs для сущности Role. В компоненте lookupField в атрибуте datasource указывается ссылка на источник данных, а в атрибуте property − название атрибута сущности, значение которого должно быть отображено. В данном случае атрибут является перечислением, и в выпадающем списке будут отображены локализованные названия всех значений этого перечисления.

  2. Аналогично можно использовать LookupField для выбора экземпляра связанной сущности. Для формирования списка опций используется атрибут optionsDatasource:

    <dsContext>
        <datasource id="carDs" class="com.company.sample.entity.Car" view="_local"/>
        <collectionDatasource id="coloursDs" class="com.company.sample.entity.Colour" view="_local">
            <query>select c from sample$Colour c</query>
        </collectionDatasource>
    </dsContext>
    <layout>
        <lookupField datasource="carDs" property="colour" optionsDatasource="coloursDs"/>

    В данном случае компонент отобразит отобразит имена экземпляров сущности Colour, находящихся в источнике данных colorsDs, а выбранное значение подставится в атрибут colour сущности Car, находящейся в источнике данных carDs.

    С помощью атрибута captionProperty можно указать, какой атрибут сущности использовать вместо имени экземпляра для строковых названий опций.

  3. Список опций компонента может быть задан произвольно с помощью методов setOptionsList(), setOptionsMap() и setOptionsEnum(), либо с помощью XML-атрибута optionsDatasource.

    • Метод setOptionsList() позволяет программно задать список опций компонента. Для этого объявляем компонент в XML-дескрипторе:

      <lookupField id="numberOfSeatsField" datasource="modelDs" property="numberOfSeats"/>

      Затем инжектируем компонент в контроллер и в методе init() задаем ему список опций:

      @Inject
      protected LookupField numberOfSeatsField;
      
      @Override
      public void init(Map<String, Object> params) {
          List<Integer> list = new ArrayList<>();
          list.add(2);
          list.add(4);
          list.add(5);
          list.add(7);
          numberOfSeatsField.setOptionsList(list);
      }

      В выпадающем списке компонента отобразятся числа 2, 4, 5, 7. Выбранное число подставится в атрибут numberOfSeats сущности, находящейся в источнике данных modelDs.

    • Метод setOptionsMap() позволяет задать строковые названия и значения опций по отдельности. Например, для описанного в XML-дескрипторе компонента numberOfSeatsField в методе init() контроллера задаем мэп опций:

      @Inject
      protected LookupField numberOfSeatsField;
      
      @Override
      public void init(Map<String, Object> params) {
          Map<String, Object> map = new LinkedHashMap<>();
          map.put("two", 2);
          map.put("four", 4);
          map.put("five", 5);
          map.put("seven", 7);
          numberOfSeatsField.setOptionsMap(map);
      }

      В выпадающем списке компонента отобразятся строки two, four, five, seven. Однако значением компонента будет число, соответствующее выбранной строке. Оно и подставится в атрибут numberOfSeats сущности, находящейся в источнике данных modelDs.

    • setOptionsEnum() принимает в качестве параметра класс перечисления. Выпадающий список будет содержать локализованные названия значений перечисления, значением компонента будет являться выбранное значение перечисления.

  • OptionsStyleProvider позволяет задать отдельные стили для различных значений в выпадающем списке с помощью метода setOptionsStyleProvider():

    lookupField.setOptionsStyleProvider((field, item) -> {
        User user = (User) item;
        switch (user.getGroup().getName()) {
            case "Company":
                return "company";
            case "Premium":
                return "premium";
            default:
                return "company";
        }
    });
  • Каждый элемент выпадающего списка может иметь значок слева. Создайте реализацию интерфейса LookupField.OptionIconProvider в контроллере экрана и установите ее для компонента lookupField:

    lookupField.setOptionIconProvider(new LookupField.OptionIconProvider<Customer>(){
        @Override
        public String getItemIcon(Customer c){
            if(c.getType()== LegalStatus.LEGAL)
                return"icons/icon-office.png";
            return"icons/icon-user.png";
        }
    });
    gui lookupField 2
    Tip

    При использовании значков в формате SVG необходимо явно указывать их размеры, чтобы избежать наложения:

    <svg version="1.1"
         id="Capa_1"
         xmlns="http://www.w3.org/2000/svg"
         xmlns:xlink="http://www.w3.org/1999/xlink"
         xml:space="preserve"
    
         style="enable-background:new 0 0 55 55;"
         viewBox="0 0 55 55"
    
         height="25px"
         width="25px">
  • Если у компонента LookupField не установлен атрибут required, и если связанный атрибут сущности не объявлен как обязательный, то в списке опций компонента присутствует пустая строка, при выборе которой компонент возвращает значение null. Атрибут nullName позволяет задать строку, отображаемую в этом случае вместо пустой. Пример использования:

    <lookupField datasource="carDs" property="colour" optionsDatasource="coloursDs" nullName="(none)"/>

    В данном случае вместо пустой строки отобразится строка (none), при выборе которой в связанный атрибут сущности подставится значение null.

    При программном задании списка опций методом setOptionsList() можно одну из опций передать в метод setNullOption(). Тогда при ее выборе пользователем значением компонента будет null.

    Фильтрация опций LookupField:
    • С помощью атрибута filterMode можно задать тип фильтрации опций при вводе пользователя:

      • NO − нет фильтрации.

      • STARTS_WITH − по началу фразы.

      • CONTAINS − по любому вхождению (используется по умолчанию).

    • Метод setFilterPredicate() позволяет настроить способ фильтрации. Предикат проверяет, совпадает ли введённая пользователем строка со заголовком элемента в списке, к примеру:

      BiFunction<String, String, Boolean> predicate = String::contains;
      lookupField.setFilterPredicate((itemCaption, searchString) ->
              predicate.apply(itemCaption.toLowerCase(), searchString));

      Функциональный интерфейс FilterPredicate содержит метод test, который позволяет реализовать более сложную логику фильтрации опций, например, игнорировать специальные символы или надстрочные знаки:

      lookupField.setFilterPredicate((itemCaption, searchString) ->
              StringUtils.replaceChars(itemCaption, "ÉÈËÏÎ", "EEEII")
                  .toLowerCase()
                  .contains(searchString));
  • Компонент LookupField способен обрабатывать ввод пользователя при отсутствии подходящей опции в списке. Для этого используются методы setNewOptionAllowed() и setNewOptionHandler(). Например:

    @Inject
    private Metadata metadata;
    
    @Inject
    protected LookupField colourField;
    
    @Inject
    protected CollectionDatasource<Colour, UUID> coloursDs;
    
    @Override
    public void init(Map<String, Object> params) {
        colourField.setNewOptionAllowed(true);
        colourField.setNewOptionHandler(new LookupField.NewOptionHandler() {
            @Override
            public void addNewOption(String caption) {
                Colour colour = metadata.create(Colour.class);
                colour.setName(caption);
                coloursDs.addItem(colour);
                colourField.setValue(colour);
            }
        });
    }

    Обработчик NewOptionHandler вызывается, если пользователь ввел некоторое значение, не совпадающее ни с одной из опций, и нажал Enter. В данном случае в обработчике создается новый экземпляр сущности Colour, его атрибут name устанавливается в значение, введенное пользователем, этот экземпляр добавляется в источник данных опций и выбирается в компоненте.

    Вместо имплементации интерфейса LookupField.NewOptionHandler для обработки ввода пользователя можно использовать XML-атрибут newOptionHandler с указанным в нем методом контроллера. Данный метод должен иметь два параметра - первый типа LookupField, второй типа String. В них будут переданы соответственно экзампляр компонента и введенное пользователем значение. Атрибут newOptionAllowed используется вместо метода setNewOptionAllowed() для того, чтобы разрешить добавление новых опций.

  • XML-атрибут nullOptionVisible устанавливает видимость элемента со значением null в списке опций. Может работать только если атрибут required имеет значение false.

  • XML-атрибут textInputAllowed используется для отключения возможности фильтрации опций с клавиатуры. Это бывает удобно для коротких списков. Значение по умолчанию - true.

  • XML-атрибут pageLength позволяет переопределить количество опций на одной странице выпадающего списка, заданное свойством приложения cuba.gui.lookupFieldPageLength.

  • В веб-клиенте с темой, основанной на Halo, к компоненту LookupField можно применить предопределенные стили. Стили задаются в XML-дексрипторе или контроллере экрана с помощью атрибута stylename:

    <lookupField id="lookupField"
                 stylename="borderless"/>

    Чтобы применить стиль программно, выберите одну из констант класса HaloTheme с префиксом компонента LOOKUPFIELD_:

    lookupField.setStyleName(HaloTheme.LOOKUPFIELD_BORDERLESS);

    Стили компонента LookupField:

    • align-center - align the text inside the field to center.

    • align-right - align the text inside the field to the right.

    • borderless - removes the border and background from the text field.