multiSelectComboBox

multiSelectComboBox позволяет пользователям выбирать один или несколько элементов из раскрывающегося списка. Этот компонент аналогичен comboBox.

XML-элемент

multiSelectComboBox

Java-класс

JmixMultiSelectComboBox

Основы

Выпадающий список открывается при нажатии на поле указателем. Если поле находится в фокусе, список также открывается клавишами Up и Down или при вводе символа.

XML
<multiSelectComboBox id="multiSelectComboBox"/>
<multiSelectComboBox itemsEnum="io.jmix.uisamples.entity.Day" clearButtonVisible="true" width="17em"/>
Java
@ViewComponent
protected JmixMultiSelectComboBox<String> multiSelectComboBox;

@Subscribe
protected void onInit(InitEvent event) {
    multiSelectComboBox.setItems("CSS", "HTML", "Java", "JavaScript", "JSON", "Kotlin", "XML");
    multiSelectComboBox.select("Java", "Kotlin");
}

multiSelectComboBox связанный с данными

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

multiSelectComboBox предназначен для свойств, которые хранят несколько значений. Когда компонент привязан к атрибуту сущности, тип атрибута должен быть коллекцией, например List или Set.

Наиболее распространённый сценарий использования — выбор связанных сущностей для связи «многие ко многим»:

Хобби.java
@JmixEntity
@Table(name = "HOBBY")
@Entity
public class Hobby {
    /* attributes */
}
User.java
@JmixEntity
@Entity
@Table(name = "USER_")
public class User {

    /* other attributes */

    @JoinTable(name = "USER_HOBBY_LINK",
            joinColumns = @JoinColumn(name = "USER_ID"),
            inverseJoinColumns = @JoinColumn(name = "HOBBY_ID"))
    @ManyToMany
    private List<Hobby> userHobbies;
}

В этом случае multiSelectComboBox позволяет пользователю выбрать несколько экземпляров Hobby, а связь сохраняется в таблице связей.

Чтобы создать multiSelectComboBox, работающий с данными, используйте атрибуты dataContainer и property, чтобы привязать компонент к свойству-коллекции. Используйте атрибут itemsContainer, чтобы задать список доступных элементов. Следующий пример создаёт multiSelectComboBox, работающий с данными.

XML
<data>
    <instance id="productDc"
              class="io.jmix.uisamples.entity.Product"
              fetchPlan="_local">
    </instance>
    <collection id="productTagsDc"
                class="io.jmix.uisamples.entity.ProductTag"
                fetchPlan="_local">
        <loader id="productTagsDl">
            <query>
                <![CDATA[select e from ProductTag e]]>
            </query>
        </loader>
    </collection>
</data>
<facets>
    <dataLoadCoordinator auto="true"/>
</facets>
<layout>
    <multiSelectComboBox id="multiSelectComboBox" width="15em" label="Product tags"
                         dataContainer="productDc" property="tags"
                         itemsContainer="productTagsDc"/>
    <hbox>
        <span text="Value in the container:"/>
        <span id="spanValue"/>
    </hbox>
</layout>
Java
@ViewComponent
protected InstanceContainer<Product> productDc;
@ViewComponent
protected Span spanValue;

@Autowired
protected Metadata metadata;

@Subscribe
protected void onInit(InitEvent event) {
    Product product = metadata.create(Product.class);
    productDc.setItem(product);
}

@Subscribe("multiSelectComboBox")
protected void onMultiSelectComboBoxFieldValueChange(
        TypedValueChangeEvent<JmixMultiSelectComboBox<Product>, Product> changeEvent) {
    spanValue.setText(getSelectedTagsInstanceName());
}

protected String getSelectedTagsInstanceName() {
    return productDc.getItem().getTags()
            .stream()
            .map(ProductTag::getInstanceName)
            .collect(Collectors.joining(", "));
}

itemsContainer определяет доступные варианты в выпадающем списке. Выбранные значения хранятся в свойстве-коллекции, указанном атрибутами dataContainer и property.

Значение компонента содержит выбранные элементы. Когда компонент привязан к свойству-коллекции, Jmix преобразует выбранные элементы к типу коллекции свойства, например List или Set.

MultiSelectComboBox c MetaClass

Вы можете использовать multiSelectComboBox без прямой ссылки на данные, то есть без указания атрибутов dataContainer и property. В этом случае используйте атрибут metaClass для указания типа сущности для multiSelectComboBox. Чтобы указать набор экземпляров для выбора, используйте атрибут itemsContainer.

Например, компонент может работать с сущностью Hobby, которая имеет имя класса метаданных Hobby.

<multiSelectComboBox metaClass="Hobby"
                     itemsContainer="userHobbiesDc"/>

Общие функции comboBox

multiSelectComboBox поддерживает следующие функции из обычного comboBox:

Пользовательские этикетки для предметов

Установите itemLabelGenerator, чтобы настроить отображение значений во всплывающем списке и чипах выбранных элементов.

XML
<data>
    <collection id="productTagsDc"
                class="io.jmix.uisamples.entity.ProductTag"
                fetchPlan="_local">
        <loader id="productTagsDl">
            <query>
                <![CDATA[select e from ProductTag e]]>
            </query>
        </loader>
    </collection>
</data>
    <multiSelectComboBox id="multiSelectComboBox" label="Product tags" itemsContainer="productTagsDc"/>
Java
@Install(to = "multiSelectComboBox", subject = "itemLabelGenerator")
protected String multiSelectComboBoxItemLabelGenerator(ProductTag productTag) {
    return "#" + productTag.getName();
}

Пользовательский рендерер предметов

Передайте компонентный рендерер, чтобы отображать во всплывающем списке составные элементы. В примере каждое значение перечисления показано со значком Vaadin и именем.

XML
<multiSelectComboBox id="iconsMultiSelectComboBox" clearButtonVisible="true"
          label="Icons"
          width="20em"/>
Java
@ViewComponent
protected JmixMultiSelectComboBox<VaadinIcon> iconsMultiSelectComboBox;

@Autowired
protected UiComponents uiComponents;

@Subscribe
protected void onInit(InitEvent event) {
    iconsMultiSelectComboBox.setItems(VaadinIcon.values());
}

@Supply(to = "iconsMultiSelectComboBox", subject = "renderer")
protected Renderer<VaadinIcon> multiSelectComboBoxComponentRenderer() {
    return new ComponentRenderer<>(vaadinIcon -> {
        HorizontalLayout contentBox = uiComponents.create(HorizontalLayout.class);
        contentBox.setPadding(false);

        contentBox.add(vaadinIcon.create());
        contentBox.add(vaadinIcon.name());

        return contentBox;
    });
}

Автоматическое расширение

Вы можете настроить multiSelectComboBox для автоматического увеличения ширины, чтобы вместить теги, представляющие выбранные элементы. Расширение работает только с неопределённым размером в нужном направлении (например, установка max-width ограничивает ширину компонента). Возможные значения:

  • VERTICAL - поле расширяется вертикально, и теги переносятся на следующую строку.

  • HORIZONTAL — поле расширяется по горизонтали до достижения максимальной ширины, затем сжимается до переполнения чипа.

  • BOTH — поле расширяется по горизонтали до достижения максимальной ширины, затем расширяется по вертикали и происходит перенос фишек.

  • NONE - поле не расширяется и сворачивается до переполнения чипа.

    == Отображение выбранных элементов

Атрибут selectedItemsOnTop управляет способом отображения выбранных элементов в выпадающем списке.

Как это работает:

  • Если selectedItemsOnTop установлен в true, выбранные элементы отображаются в верхней части выпадающего списка, а не выбранные остаются внизу. Такое расположение может быть визуально привлекательным и интуитивно понятным, особенно если пользователи часто выбирают подмножество элементов и нуждаются в быстром доступе к последним выбранным.

  • Если selectedItemsOnTop установлен в false (значение по умолчанию), выбранные элементы отображаются в том порядке, в котором они были выбраны, без перемещения в верхнюю часть выпадающего списка. Такое расположение сохраняет порядок выбора и может быть предпочтительным в сценариях, где порядок имеет решающее значение, или если важна визуальная согласованность с другими элементами интерфейса.

Получение элементов списка

multiSelectComboBox может загружать элементы по частям в ответ на действия пользователя.

Например, когда пользователь вводит foo, компонент загружает из базы данных не более 50 элементов, содержащих foo в названии, и показывает их в выпадающем списке. Когда пользователь прокручивает список вниз, компонент извлекает следующую группу из 50 элементов с тем же запросом и добавляет их в список.

Декларативная конфигурация

Для реализации этого поведения определите вложенный элемент itemsQuery.

Элемент itemsQuery должен содержать текст запроса JPQL во вложенном элементе query и несколько дополнительных атрибутов, определяющих, что и как загружать данные:

  • escapeValueForLike - включает поиск значений, содержащих специальные символы: %, \, и так далее. Значение по умолчанию - false.

  • searchStringFormat - строка Groovy. C её помощью вы можете использовать любые допустимые строковые выражения Groovy.

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

  • fetchPlan - необязательный атрибут, указывающий фетч-план для загрузки запрошенной сущности.

Элемент itemsQuery содержит следующие вложенные элементы:

  • query - элемент, содержащий запрос JPQL.

  • fetchPlan - необязательный элемент, задающий встроенный фетч-план.

Пример использования itemsQuery в multiSelectComboBox:

<multiSelectComboBox id="declarativeMultiSelectComboBox" label="Customer"
                metaClass="Customer">
    <itemsQuery class="io.jmix.uisamples.entity.Customer"
                searchStringFormat="(?i)%${inputString}%"
                escapeValueForLike="true"
                fetchPlan="_local">
        <query>
            <![CDATA[select e from Customer e where e.name
            like :searchString escape '\' order by e.name asc]]>
        </query>
    </itemsQuery>
</multiSelectComboBox>

itemsQuery не поддерживает использование префиксов container_ или component_ для автоматической привязки параметров к контейнерам или визуальным компонентам; такая декларативная привязка поддерживается только фасетом dataLoadCoordinator.

Программная конфигурация

Извлечение элементов также может быть определено программно с помощью обработчика itemsFetchCallback. Например:

@Autowired
protected DataManager dataManager;

protected Collection<Customer> customers;

@Subscribe
protected void onInit(InitEvent event) {
    customers = dataManager.load(Customer.class).all().list();
}

@Install(to = "programmaticMultiSelectComboBox", subject = "itemsFetchCallback")
protected Stream<Customer> programmaticMultiSelectComboBoxItemsFetchCallback(Query<Customer, String> query) {
    String enteredValue = query.getFilter()
            .orElse("");

    return customers.stream()
            .filter(customer -> customer.getName() != null &&
                    customer.getName().toLowerCase().contains(enteredValue.toLowerCase()))
            .skip(query.getOffset())
            .limit(query.getLimit());
}

В этом примере данные извлекаются с помощью DataManager, но вы можете использовать этот подход для загрузки из собственного сервиса.

Валидация

Чтобы проверить значения, введённые в компонент multiSelectComboBox, вы можете использовать валидатор в элементе validators.

Доступны следующие предопределённые валидаторы для multiSelectComboBox:

XML-элемент

validators

Предопределённые валидаторы

custom - notEmpty - notNull - size

Варианты темы

Используйте атрибут themeNames, чтобы применить один или несколько вариантов темы.

Вариант Описание Поддерживается в

small

Уменьшает размер компонента.

Aura, Lumo

align-left

Выравнивает значение поля по левому краю.

Aura, Lumo

align-center

Выравнивает значение поля по центру.

Aura, Lumo

align-right

Выравнивает значение поля по правому краю.

Aura, Lumo

helper-above-field

Размещает вспомогательный текст над полем, под меткой.

Aura, Lumo

Атрибуты

multiSelectComboBox имеет следующие уникальные атрибуты:

Имя Описание По умолчанию

allowCustomValue

Определяет, могут ли пользователи вводить значения, отсутствующие среди доступных элементов.

autoExpand

Управляет поведением компонента, когда недостаточно места для отображения всех выбранных элементов в виде фишек в пределах текущей ширины поля. См. Автоматическое расширение.

NONE

autoOpen

Определяет, открывается ли всплывающий список элементов при получении полем фокуса.

clearButtonVisible

Определяет, отображается ли в поле кнопка очистки.

false

itemsContainer

Задаёт контейнер элементов.

itemsEnum

Задаёт перечисление элементов.

metaClass

Определяет класс сущности для multiSelectComboBox. Установите этот атрибут, если компонент не связан с контейнером данных. В противном случае тип сущности определяется контейнером данных. См. MultiSelectComboBox с метаклассом.

opened

Определяет, открыт ли выпадающий список.

false

overlayClass

Добавляет имена CSS-классов во всплывающий элемент компонента.

pageSize

Задаёт размер страницы.

selectedItemsOnTop

Включает или отключает группировку выбранных элементов вверху наложения. См. Выбранные элементы сверху.

false

multiSelectComboBox имеет следующие общие атрибуты:

Обработчики

multiSelectComboBox имеет следующие уникальные обработчики:

Имя Описание

CustomValueSetEvent

Возникает, когда пользователь вводит в поле пользовательское значение.

itemLabelGenerator

com.vaadin.flow.component.ItemLabelGenerator можно использовать для настройки строки, отображаемой пользователю для элемента. См. itemLabelGenerator для comboBox и интерактивный пример.

itemsFetchCallback

Этот обработчик извлекает данные только тогда, когда это необходимо. См. Обратный вызов получения предметов.

renderer

Устанавливает Renderer ответственным за отображение отдельных элементов в списке возможных вариантов multiSelectComboBox. Это не влияет на то, как отображается выбранный элемент — это можно настроить с помощью ItemLabelGenerator. См. интерактивный пример.

validator

Проверяет значение компонента.

multiSelectComboBox имеет следующие общие обработчики:

Элементы

Компонент multiSelectComboBox может содержать следующие вложенные элементы: fragmentRenderer, itemsQuery, tooltip, и validator.