Filter
Компонент Filter
– универсальное средство фильтрации данных.
Компонент позволяет производить быструю фильтрацию данных по произвольному набору условий, а также создавать фильтры для многократного использования.
XML-имя компонента: filter
.
Основы
Filter
должен быть связан с загрузчиком данных независимого CollectionContainer
или KeyValueCollectionContainer
. Он генерирует объект Condition
, который устанавливается в загрузчик и затем обрабатывается хранилищем данных. Для JPA-сущности хранилище данных изменяет результирующий запрос JPQL. Таким образом, фильтрация осуществляется на уровне БД, и в память приложения загружаются только отобранные данные.
По умолчанию Jmix Studio генерирует Filter
при создании для сущности экранов браузера и master-detail.
Ниже представлен пример декларации filter
в XML-дескрипторе экрана:
<data>
<collection id="customersDc" class="ui.ex1.entity.Customer">
<fetchPlan extends="_base">
<property fetchPlan="_base" name="city"/>
<property name="favouriteBrands" fetchPlan="_base"/>
</fetchPlan>
<loader id="customersDl">
<query>
<![CDATA[select e from uiex1_Customer e]]>
</query>
</loader>
</collection>
</data>
<layout spacing="true" expand="customersTable">
<filter dataLoader="customersDl" caption="Simple filter">
<properties include=".*"/>
</filter>
<table id="customersTable"
width="100%"
dataContainer="customersDc">
<columns>
<column id="level"/>
<column id="age"/>
<column id="hobby"/>
<column id="firstName"/>
<column id="lastName"/>
<column id="city"/>
<column id="rewardPoints"/>
</columns>
</table>
</layout>
Здесь контейнер данных содержит коллекцию экземпляров сущности Customer
. Загрузчик загружает коллекцию, используя JPQL-запрос. Компонент filter
соединен с загрузчиком с помощью атрибута dataLoader
. Данные отображаются компонентом Table
, связанным с контейнером.
Типичный фильтр выглядит следующим образом:
-
Ссылка Add search condition (1).
-
Выбор оператора (4).
-
Поле со значением условия (5).
По умолчанию компонент находится в режиме быстрой фильтрации. Это означает, что пользователь может добавить набор условий для разового поиска данных. После закрытия экрана условия будут удалены.
Пример быстрого фильтра
Представим, что у нас есть сущность Customer
, и мы хотим:
-
Создать быстрый фильтр с несколькими условиями в экране Customer browser.
-
Сохранить этот фильтр на будущее.
Создание быстрого фильтра
-
Нажмите на ссылку Add search condition (1).
-
Выберите атрибут Age в списке Properties.
-
Выберите атрибут Hobby.
Выбранные условия отображаются в верхней части панели фильтра.
-
Измените оператор и значение условия:
Добавление условий
Для того чтобы создать быстрый фильтр, нажмите на ссылку Add search condition (1). Отобразится экран выбора условий:
Рассмотрим возможные типы условий:
-
Properties – атрибуты данной сущности и связанных с ней сущностей. Отображаются только персистентные и динамические атрибуты, соответствующие правилам, указанным в элементе properties.
-
Predefined conditions – условия, заданные разработчиком в элементе conditions XML-дескриптора. Предопределенные условия изначально не добавлены ни в какие фильтры, но пользователь может выбрать их на экране Add Condition и добавить в конфигурацию во время выполнения.
-
Configurations могут быть созданы во время разработки или во время выполнения (в редакторе конфигураций).
Выбранные условия отображаются в верхней части панели фильтра. Рядом с каждым условием находится кнопка , позволяющая удалить их из набора.
-
PropertyFilter
соответствует условиям по атрибутам. -
JpqlFilter
соответствует JPQL-условиям. -
GroupFilter
соответствует группирующим условиям.
При наличии в проекте дополнения Search становится доступным новое full-text условие.
Таким образом, у пользователя есть возможность создавать условия фильтрации во время выполнения.
Условия по атрибутам
Property conditions editor позволяет пользователям настраивать атрибуты компонента PropertyFilter. PropertyFilter
связан с атрибутом сущности.
Выберите атрибут сущности в поле Property.
Поле Operation поле позволяет выбрать оператор условия. Список доступных операций зависит от типа атрибута.
Используйте атрибут Parameter name, чтобы задать имя параметра запроса. Это имя можно использовать для введения зависимостей между компонентами фильтра в конфигурации. Если значение не задано, то имя параметра генерируется случайным образом.
В поле Caption можно задать собственное название условия фильтрации по атрибутам.
Флажок Operation editable используется, чтобы задать видимость выбора оператора. Если этот флажок установлен, поле операции позволит выбрать оператор условия во время выполнения.
Флажок Operation caption visible используется, чтобы задать видимость названия операции.
В поле Default value для условия можно установить значение по умолчанию.
JPQL-условия
JPQL conditions editor позволяет пользователям создавать условия на основе выражений JPQL.
В поле Parameter type нужно указать класс Java параметра условия. Значение No parameter
позволяет создать условие без параметров. Например:
Поле Caption обязательно для заполнения. В нем необходимо задать имя условия, отображаемое в фильтре.
Атрибут Parameter name используется для задания имени связанного параметра запроса. Это имя можно использовать для введения зависимостей между компонентами фильтра в конфигурации. Если значение не задано, то имя параметра генерируется случайным образом.
Флажок Has IN expression используется, чтобы определить, должно ли выражение JPQL содержать выражение IN
. В этом случае приложение будет использовать компонент ValuesPicker для создания списка значений условия.
В поле Default value для условия можно установить значение по умолчанию.
В поле Join можно указать выражение JPQL, которое будет добавлено в секцию from
запроса контейнера данных. Это может потребоваться для создания сложного условия по атрибуту связанной коллекции. Выражение должно начинаться с предложений join
или left join
. Вместо алиаса отбираемой сущности в выражении следует использовать плейсхолдер {E}
.
Значение в поле Where задает выражение JPQL, которое будет добавлено в секцию where
запроса контейнера данных. Вместо алиаса отбираемой сущности в выражении следует использовать плейсхолдер {E}
. Параметр условия может быть только один, и если он определен в поле Parameter type, обозначается символом ?
. Кроме вводимых пользователем параметров, можно использовать любое количество параметров атрибутов сессии и пользователя, например:
{E}.code = ? and {E}.area = :session_area
Группирующие условия
Group conditions editor позволяет пользователям объединять несколько условий в логическую группу.
Выпадающий список Operation позволяет пользователям выбрать оператора логической группы.
Поле Caption обязательно для заполнения. В нем необходимо задать имя условия, отображаемое в фильтре.
Флажок Operation caption visible используется, чтобы задать видимость имени операции.
Чтобы добавить условие, нажмите кнопку Add. Появится экран Add condition.
Условия фильтрации содержатся в дереве. Пользователи могут определять порядок условий фильтрации в фильтре с помощью кнопок / и удалять и редактировать условия с помощью кнопок Remove и Edit.
Конфигурация
Конфигурация – это набор компонентов фильтра.
LogicalFilterComponent
является корневым элементом конфигурации.
Конфигурация не содержит ссылок на все компоненты, а только ссылку на корневой элемент, из которого могут быть получены остальные компоненты фильтра.
Конфигурации могут быть созданы во время разработки или во время выполнения (с помощью экрана Configuration editor).
Конфигурация времени разработки
Конфигурация, созданная во время разработки, не может быть изменена и сохранена во время выполнения. Тем не менее, пользователь может использовать действие Copy
, которое копирует все условия из конфигурации времени разработки в конфигурацию времени выполнения.
Все конфигурации, созданные во время разработки, отображаются в выпадающем меню(2) сохраненных фильтров и конфигураций:
Ниже приведен пример filter
в XML-дескрипторе экрана с конфигурациями времени разработки:
<filter dataLoader="customersDl"
id="filterDesignTime"
caption="Filter with design-time configurations">
<properties include=".*"/>
<configurations>
<configuration id="configuration_age_hobby" operation="AND"
name="Age AND Hobby Configuration" default="true">
<propertyFilter property="age" operation="GREATER"/>
<propertyFilter property="hobby" operation="IN_LIST"/>
</configuration>
<configuration id="configuration_level_rewards_points" operation="OR"
name="Level OR Rewards Points Configuration">
<propertyFilter property="level" operation="EQUAL"/>
<propertyFilter property="rewardPoints" operation="LESS_OR_EQUAL"/>
</configuration>
</configurations>
</filter>
id
является обязательным атрибутом и должен быть уникальным в пределах данного фильтра. Если атрибут name
не указан, то в качестве ключа в пакете сообщений используется id
.
Используйте XML-атрибут default
, чтобы установить конфигурацию, созданную во время разработки в качестве параметра фильтра по умолчанию. Таким образом, он появляется сразу после открытия экрана.
Конфигурация времени выполнения
Чтобы создавать, редактировать или удалять конфигурации во время выполнения, пользователь должен иметь разрешение безопасности ui.filter.modifyConfiguration.
Чтобы открыть экран Configuration editor, используйте действие Edit всплывающей кнопки настроек фильтра(6).
Поле Configuration name обязательно для заполнения. В нем необходимо задать имя конфигурации, отображаемое в выпадающем меню(2) сохраненных фильтров и конфигураций.
С помощью флажка Available for all users можно установить фильтр, доступный для всех пользователей. Этот флажок доступен только пользователям, имеющим разрешение ui.filter.modifyGlobalConfiguration.
С помощью флажка Default for all users можно указать, будет ли созданная конфигурация автоматически выбираться при открытии пользователями экрана. Этот флажок доступен, если установлен флажок Available for all users.
Другие поля Configuration editor описаны в разделе Группирующие условия.
Элементы Filter
Определенный в XML-дескрипторе filter
может содержать вложенные элементы. Все они описывают условия, доступные пользователю для выбора в диалоге Add Condition:
properties
properties
позволяет сделать доступными для выбора сразу несколько атрибутов сущности. Данный элемент может иметь следующие атрибуты:
-
include
- обязательный атрибут, содержит регулярное выражение, которому должно соответствовать имя атрибута сущности.
-
exclude
- содержит регулярное выражение, при соответствии которому атрибут сущности исключается из ранее включенных с помощьюinclude
. -
excludeProperties
- содержит список атрибутов, разделенных запятыми, которые должны быть исключены из фильтрации. В отличие отexclude
, этот атрибут поддерживает путь по графу сущностей для указания каждого свойства в списке. Например,customer.name
. -
excludeRecursively
- указывает, должны ли атрибуты, перечисленные вexcludeProperties
, быть рекурсивно исключены из полного графа сущностей. Если установленоtrue
, указанный атрибут и все его вложенные атрибуты не будут использоваться в фильтре.
В примере ниже объявим компонент filter
со вложенным элементом properties
:
<filter id="filterWithProperties"
dataLoader="customersDl">
<properties include=".*"
exclude="(hobby)|(age)"
excludeProperties="id"
excludeRecursively="true"/>
</filter>
You can exclude or include dynamic attributes, using the attribute’s code with a
It is not necessary to have a dynamicAttributes facet on the screen. Pay attention, if the dynamic attribute is an entity, then the entity’s internal attributes will not be available for filtering. |
При использовании элемента properties
автоматически игнорируются следующие атрибуты сущности:
-
Недоступные в связи с разрешениями подсистемы безопасности.
-
Коллекции (
@OneToMany
,@ManyToMany
). -
Коллекции.
-
Атрибуты, аннотированные
@SystemLevel
. -
Атрибуты типа
byte[]
.
conditions
Элемент conditions
используется для создания предопределенных условий.
В примере ниже объявим компонент filter
со вложенным элементом conditions
:
<filter id="filterWithСonditions"
dataLoader="customersDl">
<properties include=".*"/>
<conditions>
<propertyFilter property="hobby"
operation="NOT_IN_LIST"
operationEditable="true"
caption="Hobby condition"/>
</conditions>
</filter>
Элемент conditions
может содержать любое количество propertyFilter, jpqlFilter или groupFilter.
configurations
Элемент configurations
используется для создания конфигураций во время разработки.
actions
actions
– это необязательный элемент, определяющий список действий для управления фильтрами.
Фреймворк предоставляет следующие действия по умолчанию во всплывающей кнопке настройки фильтра (6) :
-
Save - реализовано с помощью
FilterSaveAction
(type="filter_save"
в XML), сохраняет изменения в текущей конфигурации фильтра.
-
Save with values - реализовано с помощью
FilterSaveWithValuesAction
(type="filter_saveWithValues"
в XML), сохраняет изменения в текущем фильтре, используя значения в полях условия(5) в качестве значений фильтра по умолчанию.
-
Save as - реализовано с помощью
FilterSaveAsAction
(type="filter_saveAs"
в XML), сохраняет конфигурацию фильтра под новым именем.
-
Edit - реализовано с помощью
FilterEditAction
(type="filter_edit"
в XML), изменяет текущую конфигурацию фильтра во время выполнения (открывает экран Configuration editor). Отключено для конфигураций во время разработки.
-
Remove - реализовано с помощью
FilterRemoveAction
(type="filter_remove"
в XML), удаляет текущую конфигурацию фильтра во время выполнения. Отключено для конфигураций во время разработки.
-
Make default - реализовано с помощью
FilterMakeDefaultAction
(type="filter_makeDefault"
в XML), делает конфигурацию фильтра конфигурацией по умолчанию для этого экрана. Фильтр будет автоматически отображен на панели фильтров при открытии экрана. Имеет приоритет над атрибутом default конфигурации во время разработки и флажком Default for all users конфигурации во время выполнения. Отключено, если в экран не добавлен фасетscreenSettings
.
-
Copy - реализовано с помощью
FilterCopyAction
(type="filter_copy"
в XML), копирует все условия из конфигурации во время разработки в конфигурацию во время выполнения.
-
Clear values - реализовано с помощью
FilterClearValuesAction
(type="filter_clearValues"
в XML), очищает значения условия фильтра(5).
-
Add реализовано с помощью
FilterAddConditionAction
(type="filter_addCondition"
в XML), добавляет условие к текущей конфигурации фильтра.
Пользователи могут переопределять действия default с помощью вложенного элемента actions
. Например:
<filter id="filterWithActions"
dataLoader="customersDl">
<properties include=".*"/>
<actions>
<action id="addCondition" type="filter_addCondition"/>
<action id="clearValues" type="filter_clearValues"/>
</actions>
</filter>
Общие параметры действий можно настроить, используя XML-атрибуты элемента action
; подробности см. в разделе Действия.
Атрибуты Filter
autoApply
Атрибут autoApply
определяет, когда применяется фильтр. Если значение атрибута false
, фильтр будет применен только после нажатия кнопки Refresh. Если значение атрибута true
, фильтр применяется сразу после изменения компонентов фильтра. Значение по умолчанию указано в свойстве jmix.ui.component.filter-auto-apply.
columnsCount
Параметр columnsCount
задает количество столбцов, которые будут отображаться в одной строке. Значение по умолчанию указано в свойстве jmix.ui.component.filter-columns-count.
Разрешения
Для расширенного управления фильтрами требуются специальные разрешения:
-
Для создания/изменения/удаления конфигураций фильтра пользователь должен иметь разрешение
ui.filter.modifyConfiguration
.
-
Для создания/изменения/удаления глобальных (доступных всем пользователям) фильтров пользователь должен иметь разрешение
ui.filter.modifyGlobalConfiguration
.
-
Для создания/изменения условий JPQL во время выполнения пользователь должен иметь разрешение
ui.filter.modifyJpqlCondition
.
Вы можете либо предоставить пользователям предопределенную ресурсную роль UI: edit filters, либо настроить необходимые разрешения в своей собственной роли.
Свойства приложения
Следующие свойства приложения влияют на поведение фильтров:
Свойства jmix.ui.component.entity-field-type и jmix.ui.component.entity-field-actions задают компоненты для выбора сущностей в условиях фильтра.
Создание фильтра программно
В примере ниже программно создается компонент Filter
с конфигурацией времени разработки и добавляется в контейнер, заданный в XML-дескрипторе.
@Autowired
protected UiComponents uiComponents;
@Autowired
protected CollectionLoader<Customer> customersDl;
@Autowired
protected SingleFilterSupport singleFilterSupport;
@Autowired
protected Filter pfdtcFilter;
@Autowired
protected Filter jfdtcFilter;
@Autowired
protected JpqlFilterSupport jpqlFilterSupport;
@Autowired
protected Filter gfdtcFilter;
@Autowired
private VBoxLayout programmaticFilterContainer;
@Subscribe
protected void onAfterInit(AfterInitEvent event) {
Filter filter = uiComponents.create(Filter.class); (1)
filter.setId("programmaticFilter");
filter.setDataLoader(customersDl);
filter.loadConfigurationsAndApplyDefault();
DesignTimeConfiguration javaDefaultConfiguration =
filter.addConfiguration("javaDefaultConfiguration",
"Default configuration"); (2)
PropertyFilter<Integer> agePropertyFilter =
uiComponents.create(PropertyFilter.class); (3)
agePropertyFilter.setConditionModificationDelegated(true);
agePropertyFilter.setDataLoader(customersDl);
agePropertyFilter.setProperty("age");
agePropertyFilter.setOperation(PropertyFilter.Operation.LESS_OR_EQUAL);
agePropertyFilter.setOperationEditable(true);
agePropertyFilter.setParameterName(PropertyConditionUtils.generateParameterName(
agePropertyFilter.getProperty()));
agePropertyFilter.setValueComponent(singleFilterSupport.generateValueComponent(
customersDl.getContainer().getEntityMetaClass(),
agePropertyFilter.getProperty(),
agePropertyFilter.getOperation())); (4)
javaDefaultConfiguration.getRootLogicalFilterComponent().add(agePropertyFilter); (5)
filter.setCurrentConfiguration(javaDefaultConfiguration); (6)
programmaticFilterContainer.add(filter); (7)
}
1 | Создание Filter и установка его свойства. |
2 | Добавление конфигурации времени разработки с идентификатором javaDefaultConfiguration и названием Default configuration . |
3 | Создание PropertyFilter и установка его свойства. |
4 | Создание компонента значения с передачей мета-класса, атрибута сущностии и операции. |
5 | Добавление созданного PropertyFilter в конфигурацию javaDefaultConfiguration . |
6 | Установка конфигурации javaDefaultConfiguration как текущей. |
7 | Добавление компонента Filter в контейнер. |
События и слушатели
Чтобы сгенерировать заглушку слушателя в Jmix Studio, выберите компонент в XML-дескрипторе экрана или на панели иерархии Jmix UI и используйте вкладку Handlers на панели инспектора Jmix UI. В качестве альтернативы вы можете воспользоваться кнопкой Generate Handler на верхней панели контроллера экрана. |
ConfigurationChangeEvent
ConfigurationChangeEvent
отправляется при изменении конфигурации. Пример подписки на событие фильтра, объявленного в XML с идентификатором filter
:
@Subscribe("filter")
public void onFilterConfigurationChange(Filter.ConfigurationChangeEvent event) {
notifications.create()
.withCaption("Before: " + event.getPreviousConfiguration().getName() +
". After: " + event.getNewConfiguration().getName())
.show();
}
Чтобы создать слушателя события программно, используйте метод компонента addConfigurationChangeListener()
.
PropertiesFilterPredicate
Чтобы включать или исключать свойства из фильтрации программно, используйте PropertiesFilterPredicate
:
@Install(to = "filter", subject = "propertiesFilterPredicate")
private boolean filterPropertiesFilterPredicate(MetaPropertyPath metaPropertyPath) {
return !metaPropertyPath.getMetaProperty().getName().equals("hobby");
}
Этот предикат добавляется к текущему предикату фильтра properties и проверяет, должно ли свойство с заданным путем быть доступным для фильтрации.
Чтобы добавить предикат программно, используйте метод компонента addPropertiesFilterPredicate()
. Результирующий предикат является составным предикатом, представляющий логическое замыкание AND
заданного предиката и предиката текущего фильтра properties.
Все XML-атрибуты
Просматривать и редактировать атрибуты, применимые к компоненту, можно с помощью панели инспектора Jmix UI в конструкторе экранов Studio. |
XML-атрибуты Filter
align - autoApply - caption - captionAsHtml - captionPosition - collapsable - collapsable - colspan - columnsCount - contextHelpText - contextHelpTextHtmlEnabled - css - description - descriptionAsHtml - enable - box.expandRatio - height - htmlSanitizerEnabled - icon - id - margin - responsive - rowspan - stylename - visible - width