genericFilter
Компонент genericFilter формирует настраиваемые условия для загрузчика данных и отображает их в виде интерактивного фильтра. По умолчанию genericFilter добавляется на стандартные экраны сущностей, например на экраны списка.
XML-элемент |
|
|---|---|
Java-класс |
|
Использование во время выполнения
В зависимости от конфигурации фильтра и предоставленных разрешений пользователи могут:
-
Создавать временный фильтр, который действует, пока открыт текущий экран. Пользователи могут вводить значения условий, изменять доступные операции и сбрасывать фильтр.
-
Применять сохранённые фильтры и конфигурации, доступные в приложении. Пользователи не могут редактировать или удалять их, но могут копировать при наличии разрешения
ui.genericfilter.modifyConfiguration. -
Создавать новые условия с помощью мастеров. Эти условия эквивалентны тем, которые создают разработчики:
-
Условие по атрибуту – фильтрует по атрибуту сущности.
-
Условие JPQL – фильтрует по пользовательскому запросу.
-
Групповое условие – объединяет несколько условий с помощью
ANDилиOR. -
Условие полнотекстового поиска – выполняет поиск по настроенным атрибутам сущности. Доступно при установленном модуле Search.
-
-
Сохранять, редактировать, копировать и удалять персональные конфигурации времени выполнения при наличии разрешения
ui.genericfilter.modifyConfiguration. -
Делать конфигурацию времени выполнения доступной для всех пользователей или назначать её конфигурацией по умолчанию при наличии разрешения
ui.genericfilter.modifyGlobalConfiguration.
Основы
Для работы компонент должен ссылаться на загрузчик отдельного CollectionContainer или KeyValueCollectionContainer. Компонент формирует объект Condition и передаёт его загрузчику. Для JPA-сущностей хранилище данных преобразует условие в JPQL, поэтому фильтрация выполняется в базе данных.
В примере исходное условие по возрасту объявлено в XML, а дополнительное условие по атрибуту добавляется в Java. Идентификаторы в XML и контроллере должны совпадать, поскольку контроллер получает существующую конфигурацию и расширяет её:
<data>
<collection id="customersDc"
class="io.jmix.uisamples.entity.Customer"
fetchPlan="_local">
<loader id="customersDl">
<query>
<![CDATA[select e from Customer e]]>
</query>
</loader>
</collection>
</data>
<facets>
<dataLoadCoordinator auto="true"/>
</facets>
<layout>
<genericFilter id="genericFilter" dataLoader="customersDl">
<properties include=".*"/>
</genericFilter>
<dataGrid id="customerDataGrid"
dataContainer="customersDc"
width="100%"
minHeight="20em">
<columns>
<column property="name"/>
<column property="lastName"/>
<column property="age"/>
<column property="active"/>
<column property="grade"/>
</columns>
</dataGrid>
</layout>
@ViewComponent
protected GenericFilter genericFilter;
@Autowired
protected UiComponents uiComponents;
@Autowired
protected SingleFilterSupport singleFilterSupport;
@Subscribe
protected void onBeforeShow(BeforeShowEvent event) {
initConfiguration();
}
protected void initConfiguration() {
DataLoader dataLoader = genericFilter.getDataLoader();
PropertyFilter<Integer> agePropertyFilter = craeteAgePropertyFilter(dataLoader);
genericFilter.getCurrentConfiguration().getRootLogicalFilterComponent().add(agePropertyFilter);
genericFilter.setCurrentConfiguration(genericFilter.getCurrentConfiguration());
}
protected PropertyFilter<Integer> craeteAgePropertyFilter(DataLoader dataLoader) {
PropertyFilter<Integer> agePropertyFilter = uiComponents.create(PropertyFilter.class);
agePropertyFilter.setConditionModificationDelegated(true);
agePropertyFilter.setDataLoader(dataLoader);
agePropertyFilter.setProperty("age");
agePropertyFilter.setOperation(PropertyFilter.Operation.GREATER_OR_EQUAL);
agePropertyFilter.setOperationEditable(true);
agePropertyFilter.setParameterName(PropertyConditionUtils.generateParameterName(
agePropertyFilter.getProperty()));
agePropertyFilter.setValueComponent(singleFilterSupport.generateValueComponent(
dataLoader.getContainer().getEntityMetaClass(),
agePropertyFilter.getProperty(),
agePropertyFilter.getOperation()
));
return agePropertyFilter;
}
|
Загрузчик данных может иметь собственное базовое условие, заданное в элементе |
Условия свойства
propertyFilter преобразует атрибут сущности и операцию сравнения в условие загрузчика данных. Атрибут property принимает прямой или вложенный путь к атрибуту, а компонент создаёт поле значения в соответствии с метаданными атрибута.
В XML в конфигурацию, заданную на этапе разработки, добавляются фильтры для customer и customer.grade. Оба используют операцию EQUAL и атрибут operationEditable="true": сначала отображается операция Равно, но пользователь может изменить её на запущенном экране.
В примере Java эквивалентная конфигурация создаётся с помощью низкоуровневого API. Каждый PropertyFilter связывается с загрузчиком данных genericFilter, получает сгенерированное имя параметра и компонент значения, а также делегирует изменение условия. Затем фильтры добавляются в корневой логический компонент конфигурации.
<genericFilter id="genericFilter" dataLoader="ordersDl">
<properties include=".*"/>
<configurations>
<configuration id="defaultConfiguration" name="Configuration with property conditions" default="true">
<propertyFilter property="customer" operation="EQUAL"
operationEditable="true"/>
<propertyFilter property="customer.grade" operation="EQUAL"
operationEditable="true"/>
</configuration>
</configurations>
</genericFilter>
@ViewComponent
protected GenericFilter genericFilter;
@Autowired
protected UiComponents uiComponents;
@Autowired
protected SingleFilterSupport singleFilterSupport;
@Subscribe
protected void onInit(InitEvent event) {
initConfiguration();
}
protected void initConfiguration() {
DesignTimeConfiguration javaConfiguration = genericFilter.addConfiguration("javaConfiguration",
"Programmatically defined configuration");
DataLoader dataLoader = genericFilter.getDataLoader();
javaConfiguration.getRootLogicalFilterComponent().add(createCustomerPropertyFilter(dataLoader));
javaConfiguration.getRootLogicalFilterComponent().add(createGradePropertyFilter(dataLoader));
}
protected PropertyFilter<Customer> createCustomerPropertyFilter(DataLoader dataLoader) {
PropertyFilter<Customer> customerPropertyFilter = uiComponents.create(PropertyFilter.class);
customerPropertyFilter.setConditionModificationDelegated(true);
customerPropertyFilter.setDataLoader(dataLoader);
customerPropertyFilter.setProperty("customer");
customerPropertyFilter.setOperation(PropertyFilter.Operation.EQUAL);
customerPropertyFilter.setOperationEditable(true);
customerPropertyFilter.setParameterName(PropertyConditionUtils.generateParameterName(
customerPropertyFilter.getProperty()));
customerPropertyFilter.setValueComponent(singleFilterSupport.generateValueComponent(
dataLoader.getContainer().getEntityMetaClass(),
customerPropertyFilter.getProperty(),
customerPropertyFilter.getOperation()
));
return customerPropertyFilter;
}
protected PropertyFilter<CustomerGrade> createGradePropertyFilter(DataLoader dataLoader) {
PropertyFilter<CustomerGrade> gradePropertyFilter = uiComponents.create(PropertyFilter.class);
gradePropertyFilter.setConditionModificationDelegated(true);
gradePropertyFilter.setDataLoader(dataLoader);
gradePropertyFilter.setProperty("customer.grade");
gradePropertyFilter.setOperation(PropertyFilter.Operation.EQUAL);
gradePropertyFilter.setOperationEditable(true);
gradePropertyFilter.setParameterName(PropertyConditionUtils.generateParameterName(
gradePropertyFilter.getProperty()));
gradePropertyFilter.setValueComponent(singleFilterSupport.generateValueComponent(
dataLoader.getContainer().getEntityMetaClass(),
gradePropertyFilter.getProperty(),
gradePropertyFilter.getOperation()
));
return gradePropertyFilter;
}
Условия JPQL
jpqlFilter задаёт произвольный предикат JPQL для условий, которые нельзя выразить сравнением атрибутов. В примере заказы фильтруются по товару из коллекции items: предложение join вводит псевдоним коллекции, а where сравнивает идентификатор товара с параметром фильтра.
В XML-примере объявляется пространство имён JPQL-условия, классом параметра назначается Product, а предложения join и where помещаются внутрь condition. Во время выполнения класс параметра определяет тип компонента значения, отображаемого для условия.
В Java-примере такой же фильтр создаётся через низкоуровневый API. Предложения where и join передаются в setCondition(), задаются класс и подпись параметра, создаются имя параметра и совместимый компонент значения, после чего фильтр добавляется в программно созданную конфигурацию этапа разработки.
При определении JPQL-условия используйте следующий синтаксис:
-
Начните необязательное выражение
joinсjoinилиleft joinи используйте{E}вместо псевдонима сущности загрузчика данных. -
В
whereиспользуйте{E}для псевдонима сущности и?для значения, предоставленного фильтром. Условие может содержать только один параметр?, но также может содержать параметры атрибут сеанса и пользователя. -
Для параметра со значением коллекции, используемого в выражении
IN, включите свойствоhasInExpressionфильтра.
<view xmlns="http://jmix.io/schema/flowui/view"
xmlns:c="http://jmix.io/schema/flowui/jpql-condition">
<genericFilter id="genericFilter" dataLoader="ordersDl">
<properties include=".*"/>
<configurations>
<configuration id="defaultConfiguration" name="Configuration with JPQL condition" default="true">
<jpqlFilter label="Order items contains"
parameterClass="io.jmix.uisamples.entity.Product">
<condition>
<c:jpql>
<c:join>join {E}.items i</c:join>
<c:where>i.product.id = ?</c:where>
</c:jpql>
</condition>
</jpqlFilter>
</configuration>
</configurations>
</genericFilter>
@ViewComponent
protected GenericFilter genericFilter;
@Autowired
protected UiComponents uiComponents;
@Autowired
protected JpqlFilterSupport jpqlFilterSupport;
@Autowired
protected SingleFilterSupport singleFilterSupport;
@Subscribe
protected void onInit(InitEvent event) {
initConfiguration();
}
protected void initConfiguration() {
DesignTimeConfiguration javaConfiguration = genericFilter.addConfiguration("javaConfiguration",
"Programmatically defined configuration");
DataLoader dataLoader = genericFilter.getDataLoader();
javaConfiguration.getRootLogicalFilterComponent().add(createProductJpqlFilter(dataLoader));
}
protected JpqlFilter<Product> createProductJpqlFilter(DataLoader dataLoader) {
JpqlFilter<Product> jpqlFilter = uiComponents.create(JpqlFilter.class);
jpqlFilter.setConditionModificationDelegated(true);
jpqlFilter.setDataLoader(dataLoader);
jpqlFilter.setCondition("i.product.id = ?", "join {E}.items i");
jpqlFilter.setParameterClass(Product.class);
jpqlFilter.setLabel("Order items contains");
jpqlFilter.setParameterName(jpqlFilterSupport.generateParameterName(
jpqlFilter.getId().orElse(null),
jpqlFilter.getParameterClass().getSimpleName()));
jpqlFilter.setValueComponent(singleFilterSupport.generateValueComponent(
dataLoader.getContainer().getEntityMetaClass(),
jpqlFilter.hasInExpression(),
jpqlFilter.getParameterClass()
));
return jpqlFilter;
}
Условия группы
groupFilter объединяет вложенные компоненты фильтра с AND или OR. Группы могут быть вложенными, а корневой логический компонент конфигурации объединяет своих прямых дочерних элементов со своей собственной операцией.
В XML-примере создаётся группа OR с фильтрами по атрибутам active и grade. Фильтр age находится вне этой группы, поэтому корневая операция по умолчанию формирует следующее выражение:
(active = false OR grade = STANDARD) AND age >= 30
В примере Java явно создаётся такое же дерево условий. Код создаёт групповой фильтр и фильтры по атрибутам, добавляет фильтры по атрибутам в группу, а затем помещает группу и фильтр age в корень конфигурации. Для каждого компонента задаются текущее и сохранённое значения, поэтому при выборе конфигурации восстанавливаются те же значения.
<genericFilter id="genericFilter" dataLoader="customersDl">
<properties include=".*"/>
<configurations>
<configuration id="defaultConfiguration" name="Configuration with conditions grouping" default="true">
<groupFilter operation="OR">
<propertyFilter property="active" operation="EQUAL"
operationEditable="true" defaultValue="false"/>
<propertyFilter property="grade" operation="EQUAL"
operationEditable="true" defaultValue="30"/>
</groupFilter>
<propertyFilter property="age" operation="GREATER_OR_EQUAL"
operationEditable="true" defaultValue="30"/>
</configuration>
</configurations>
</genericFilter>
@ViewComponent
protected GenericFilter genericFilter;
@Autowired
protected UiComponents uiComponents;
@Autowired
protected SingleFilterSupport singleFilterSupport;
@Autowired
protected LogicalFilterSupport logicalFilterSupport;
@Subscribe
protected void onInit(InitEvent event) {
initConfiguration();
}
protected void initConfiguration() {
DesignTimeConfiguration javaConfiguration = genericFilter.addConfiguration("javaConfiguration",
"Programmatically defined configuration");
DataLoader dataLoader = genericFilter.getDataLoader();
GroupFilter groupFilter = createGroupFilter(dataLoader);
PropertyFilter<Boolean> activePropertyFilter = createActivePropertyFilter(dataLoader);
PropertyFilter<CustomerGrade> gradePropertyFilter = createGradePropertyFilter(dataLoader);
groupFilter.add(activePropertyFilter);
groupFilter.add(gradePropertyFilter);
PropertyFilter<Integer> agePropertyFilter = createAgePropertyFilter(dataLoader);
javaConfiguration.getRootLogicalFilterComponent().add(groupFilter);
javaConfiguration.getRootLogicalFilterComponent().add(agePropertyFilter);
activePropertyFilter.setValue(false);
javaConfiguration.setFilterComponentDefaultValue(activePropertyFilter.getParameterName(), false);
gradePropertyFilter.setValue(CustomerGrade.STANDARD);
javaConfiguration.setFilterComponentDefaultValue(gradePropertyFilter.getParameterName(), CustomerGrade.STANDARD);
agePropertyFilter.setValue(30);
javaConfiguration.setFilterComponentDefaultValue(agePropertyFilter.getParameterName(), 30);
}
protected GroupFilter createGroupFilter(DataLoader dataLoader) {
GroupFilter groupFilter = uiComponents.create(GroupFilter.class);
groupFilter.setConditionModificationDelegated(true);
groupFilter.setDataLoader(dataLoader);
groupFilter.setOperation(LogicalFilterComponent.Operation.OR);
return groupFilter;
}
protected PropertyFilter<Boolean> createActivePropertyFilter(DataLoader dataLoader) {
PropertyFilter<Boolean> activePropertyFilter = uiComponents.create(PropertyFilter.class);
activePropertyFilter.setConditionModificationDelegated(true);
activePropertyFilter.setDataLoader(dataLoader);
activePropertyFilter.setProperty("active");
activePropertyFilter.setOperation(PropertyFilter.Operation.EQUAL);
activePropertyFilter.setOperationEditable(true);
activePropertyFilter.setParameterName(PropertyConditionUtils.generateParameterName(
activePropertyFilter.getProperty()));
activePropertyFilter.setValueComponent(singleFilterSupport.generateValueComponent(
dataLoader.getContainer().getEntityMetaClass(),
activePropertyFilter.getProperty(),
activePropertyFilter.getOperation()
));
return activePropertyFilter;
}
protected PropertyFilter<CustomerGrade> createGradePropertyFilter(DataLoader dataLoader) {
PropertyFilter<CustomerGrade> gradePropertyFilter = uiComponents.create(PropertyFilter.class);
gradePropertyFilter.setConditionModificationDelegated(true);
gradePropertyFilter.setDataLoader(dataLoader);
gradePropertyFilter.setProperty("grade");
gradePropertyFilter.setOperation(PropertyFilter.Operation.EQUAL);
gradePropertyFilter.setOperationEditable(true);
gradePropertyFilter.setParameterName(PropertyConditionUtils.generateParameterName(
gradePropertyFilter.getProperty()));
gradePropertyFilter.setValueComponent(singleFilterSupport.generateValueComponent(
dataLoader.getContainer().getEntityMetaClass(),
gradePropertyFilter.getProperty(),
gradePropertyFilter.getOperation()
));
return gradePropertyFilter;
}
protected PropertyFilter<Integer> createAgePropertyFilter(DataLoader dataLoader) {
PropertyFilter<Integer> agePropertyFilter = uiComponents.create(PropertyFilter.class);
agePropertyFilter.setConditionModificationDelegated(true);
agePropertyFilter.setDataLoader(dataLoader);
agePropertyFilter.setProperty("age");
agePropertyFilter.setOperation(PropertyFilter.Operation.GREATER_OR_EQUAL);
agePropertyFilter.setOperationEditable(true);
agePropertyFilter.setParameterName(PropertyConditionUtils.generateParameterName(
agePropertyFilter.getProperty()));
agePropertyFilter.setValueComponent(singleFilterSupport.generateValueComponent(
dataLoader.getContainer().getEntityMetaClass(),
agePropertyFilter.getProperty(),
agePropertyFilter.getOperation()
));
return agePropertyFilter;
}
Конфигурация времени разработки
Конфигурация фильтра — именованное дерево условий, зарегистрированное в genericFilter. Конфигурация этапа разработки объявляется в XML-дескрипторе экрана с помощью элемента configurations фильтра.
В примере в одной конфигурации объявлены три фильтра по атрибутам. Атрибут default="true" активирует эту конфигурацию при открытии экрана, поэтому значения по умолчанию сразу отображаются в созданных полях:
<genericFilter id="genericFilter" dataLoader="customersDl">
<properties include=".*"/>
<configurations>
<configuration id="defaultConfiguration" name="Configuration with multiple conditions"
default="true">
<propertyFilter property="age" operation="GREATER_OR_EQUAL"
operationEditable="true" defaultValue="30"/>
<propertyFilter property="grade" operation="EQUAL"
operationEditable="true" defaultValue="20"/>
<propertyFilter property="active" operation="EQUAL"
operationEditable="true" defaultValue="true"/>
</configuration>
</configurations>
</genericFilter>
Для каждой конфигурации задайте атрибут id с уникальным в пределах этого genericFilter значением. Если атрибут name не указан, id используется как ключ в пакете сообщений. Конфигурация по умолчанию задаётся атрибутом default.
Чтобы добавить конфигурацию времени разработки в Jmix Studio, выберите компонент genericFilter в дескрипторе экрана или на панели структуры Jmix UI, затем используйте пункт меню Add → Configurations → Design-time configuration на панели Component Inspector.
|
Конфигурация этапа разработки отображается в списке конфигураций, но во время выполнения её дерево условий нельзя изменить или удалить. Действие Копировать создаёт на её основе редактируемую пользовательскую конфигурацию. См. Сохранение конфигураций и управление ими.
Создание фильтра программно
Создавать и настраивать genericFilter в Java можно с помощью fluent API билдеров с двумя точками входа:
-
filterComponentBuilder()создаёт компоненты фильтра —propertyFilter,jpqlFilterиgroupFilter. -
runtimeConfigurationBuilder()собираетRunTimeConfigurationиз этих компонентов и регистрирует его в фильтре.
Билдер выполняет всю необходимую инициализацию внутри (делегирование модификации условий, генерацию имени параметра и компонента значения), поэтому программно созданный компонент ведёт себя точно так же, как объявленный в XML. У владеющего им genericFilter должен быть DataLoader, иначе методы билдера выбрасывают IllegalStateException.
| В настоящее время fluent API билдеров является экспериментальным и может измениться в будущих версиях Jmix. |
Следующий пример создаёт genericFilter, строит условие по свойству и регистрирует конфигурацию:
@Autowired
private UiComponents uiComponents;
@ViewComponent
private VerticalLayout programmaticFilterBox;
@ViewComponent
private CollectionLoader<Customer> customerDl;
@Subscribe
public void onInit(final InitEvent event) {
GenericFilter genericFilter = uiComponents.create(GenericFilter.class); (1)
genericFilter.setId("programmaticFilter");
genericFilter.setDataLoader(customerDl);
genericFilter.loadConfigurationsAndApplyDefault();
programmaticFilterBox.add(genericFilter); (2)
PropertyFilter<Integer> agePropertyFilter = genericFilter.filterComponentBuilder() (3)
.<Integer>propertyFilter()
.property("age")
.operation(PropertyFilter.Operation.LESS_OR_EQUAL)
.operationEditable(true)
.build();
genericFilter.runtimeConfigurationBuilder() (4)
.id("javaConfiguration")
.name("Default configuration")
.add(agePropertyFilter)
.makeCurrent() (5)
.buildAndRegister(); (6)
}
| 1 | Создаёт genericFilter с помощью фабрики uiComponents. |
| 2 | Помещает genericFilter на экран внутрь контейнера vbox, объявленного в дескрипторе экрана и инжектированного в контроллер. |
| 3 | Строит PropertyFilter с помощью filterComponentBuilder(). |
| 4 | Регистрирует конфигурацию времени выполнения с помощью runtimeConfigurationBuilder() и добавляет в неё фильтр. |
| 5 | Немедленно активирует конфигурацию. Это не постоянный маркер конфигурации по умолчанию, он просто делает конфигурацию текущей. |
| 6 | Строит и регистрирует конфигурацию. Каждый экземпляр билдера одноразовый. |
Создание компонентов фильтра
filterComponentBuilder() возвращает отдельный билдер для каждого типа компонента. Все билдеры одноразовые и создают готовый к добавлению компонент.
Property Filter
propertyFilter() фильтрует по атрибуту сущности, включая вложенные ссылки — property() принимает путь вида customer.city.name. Редактор значения генерируется автоматически на основе типа атрибута. Операция фиксирована, если вы не вызовете operationEditable(true), что позволяет пользователю изменять её во время выполнения; operationTextVisible(false) скрывает метку операции, отображаемую рядом с полем. Значение, переданное в defaultValue(), предзаполняет поле.
PropertyFilter<Integer> ageFilter = genericFilter.filterComponentBuilder()
.<Integer>propertyFilter()
.property("age")
.operation(PropertyFilter.Operation.GREATER_OR_EQUAL)
.operationEditable(true)
.build();
JPQL Filter (Checkbox)
jpqlFilter() (без аргумента) создаёт void-фильтр: флажок, который включает и выключает фиксированное условие WHERE. Его тип значения — Boolean, поэтому defaultValue(true) делает условие активным по умолчанию.
JpqlFilter<Boolean> hasRewardPoints = genericFilter.filterComponentBuilder()
.jpqlFilter()
.where("{E}.rewardPoints > 0")
.label("Has reward points")
.defaultValue(true)
.build();
JPQL Filter (Typed)
jpqlFilter(Class) создаёт типизированный фильтр: значение, вводимое пользователем, привязывается к параметру запроса, а его редактор соответствует указанному Class. Напишите условие в where(), используя {E} в качестве псевдонима сущности и именованный параметр, затем объявите его имя с помощью parameterName(). Добавьте join(), чтобы расширить часть FROM, или hasInExpression(true), когда значение является коллекцией (условие in).
JpqlFilter<Integer> minAge = genericFilter.filterComponentBuilder()
.jpqlFilter(Integer.class)
.where("{E}.age >= :minAge")
.parameterName("minAge")
.label("Minimum age")
.build();
Group Filter
groupFilter() объединяет условия под одной логической операцией — AND (по умолчанию) или OR. Группа сама является компонентом фильтра, поэтому группы можно вкладывать друг в друга для выражения сложной булевой логики. Добавляйте дочерние элементы с помощью add() или addAll().
GroupFilter orGroup = genericFilter.filterComponentBuilder()
.groupFilter()
.operation(LogicalFilterComponent.Operation.OR)
.addAll(hasRewardPoints, minAge)
.build();
Создание конфигурации времени выполнения
runtimeConfigurationBuilder() создаёт RunTimeConfiguration и регистрирует его в фильтре.
genericFilter.runtimeConfigurationBuilder()
.id("dynamicConfiguration")
.name("Dynamic configuration")
.add(ageFilter, 18) (1)
.add(orGroup) (2)
.makeCurrent() (3)
.allowDeletion() (4)
.buildAndRegister();
| 1 | Добавляет компонент с типизированным значением по умолчанию; тип значения проверяется во время компиляции. Используйте add(component) без значения по умолчанию или addAll(components…), чтобы добавить несколько сразу. |
| 2 | Добавляет группу, построенную выше. |
| 3 | Немедленно активирует конфигурацию. Это не постоянный маркер конфигурации по умолчанию. |
| 4 | Позволяет пользователю удалить эту конфигурацию. По умолчанию конфигурации, созданные с помощью билдера, защищены от удаления пользователем. |
Учтите:
-
Каждый экземпляр билдера одноразовый — повторный вызов
build()илиbuildAndRegister()выбрасываетIllegalStateException. -
idконфигурации должен быть уникальным в пределах фильтра. -
У владеющего ею
genericFilterдолжен бытьDataLoader.
Билдер создаёт RunTimeConfiguration. Билдера для DesignTimeConfiguration не существует. Чтобы создавать конфигурации программно на более низком уровне, используйте addConfiguration(id, name) (который возвращает DesignTimeConfiguration) и создавайте и добавляйте компоненты фильтра напрямую, либо постройте RunTimeConfiguration и зарегистрируйте её с помощью addConfiguration(configuration). Это более низкоуровневый подход, который заменяет API билдеров.
|
| Готовые примеры всех возможностей билдера см. в разделе GenericFilter в UI Samples. |
Разрешения
Чтобы пользователи могли настраивать фильтр, предоставьте следующие специальные разрешения:
-
ui.genericfilter.modifyConfigurationпозволяет пользователям создавать, редактировать и удалять собственные конфигурации времени выполнения. -
ui.genericfilter.modifyGlobalConfigurationпозволяет пользователям создавать, редактировать и удалять конфигурации, доступные всем пользователям. -
ui.genericfilter.modifyJpqlConditionпозволяет пользователям создавать и изменять условия JPQL во время выполнения.
Варианты темы
Используйте атрибут themeNames для настройки темы компонента.
| Вариант | Описание | Поддерживается в |
|---|---|---|
|
Применяет стиль с заливкой фона к заголовку фильтра. |
Aura, Lumo |
|
Размещает индикатор переключения перед текстом сводки. |
Aura, Lumo |
|
Делает заголовок фильтра более компактным. |
Aura, Lumo |
Атрибуты
genericFilter имеет следующие уникальные атрибуты:
| Имя | Описание | По умолчанию |
|---|---|---|
Задаёт сочетание клавиш, которое применяет условия, если автоматическое применение отключено. |
||
Определяет, применяется ли изменённое условие немедленно. Если указано |
||
Ссылается на загрузчик данных, который получает сгенерированное условие. |
— |
|
Определяет, будет ли развернута панель условий. |
|
|
Устанавливает, сколько уровней вложенных атрибутов сущности может быть предложено в качестве условий. |
|
|
Устанавливает сводку, отображаемую над панелью условий. |
|
genericFilter имеет следующие общие атрибуты:
Обработчики
genericFilter имеет следующие уникальные обработчики:
| Имя | Описание |
|---|---|
Срабатывает при изменении текущей конфигурации, включая выбор и сброс. |
|
Срабатывает после редактирования текущей конфигурации. |
|
Срабатывает при изменении состояния |
|
Проверяет атрибуты сущности перед добавлением в список атрибутов, доступных для создаваемых пользователем условий. |
genericFilter имеет следующие общие обработчики:
Элементы
genericFilter может содержать элементы actions, conditions, configurations, properties, responsiveSteps и tooltip. В следующих подразделах описаны элементы конфигурации, относящиеся к фильтру.
actions
Определяет список действий для управления фильтром. По умолчанию в меню
Настройки фильтра доступны следующие действия:
-
Сохранить — сохраняет изменения в текущей конфигурации. Реализовано
FilterSaveAction(type="genericFilter_save"в XML). -
Сохранить со значениями — сохраняет изменения в текущей конфигурации вместе со значениями в полях условий [5] в качестве значений по умолчанию.
-
Сохранить как — сохраняет текущую конфигурацию под другим именем. Реализовано
FilterSaveAsAction(type="genericFilter_saveAs"в XML). -
Редактировать — открывает редактор текущей конфигурации времени выполнения. Недоступно для конфигураций времени разработки. Реализовано классом
FilterEditAction(type="genericFilter_edit"в XML). -
Удалить — удаляет текущую конфигурацию времени выполнения. Недоступно для конфигураций времени разработки. Реализовано классом
FilterRemoveAction(type="genericFilter_remove"в XML). -
Копировать — создаёт копию текущей конфигурации времени выполнения. Реализовано классом
FilterCopyAction(type="genericFilter_copy"в XML). -
Очистить значения — очищает значения в полях условий [5]. Реализовано классом
FilterClearValuesAction(type="genericFilter_clearValues"в XML). -
Добавить — добавляет условие в текущую конфигурацию. Реализовано
FilterAddConditionAction(type="genericFilter_addCondition"в XML). -
Сбросить — возвращает компонент к пустому быстрому фильтру. Реализовано классом
FilterResetAction(type="genericFilter_reset"в XML).
Разработчики могут переопределить список действий в меню настроек
:
<genericFilter id="filterWithActions" dataLoader="customerDl">
<properties include=".*"/>
<actions>
<action id="addCondition" type="genericFilter_addCondition"/>
<action id="clearValues" type="genericFilter_reset"/>
</actions>
</genericFilter>
В примере стандартный список действий заменяется действиями Добавить и Сбросить.
conditions
Содержит объявления предопределённых условий.
Пример:
<genericFilter id="filterWithCondition" dataLoader="customerDl">
<properties include=".*"/>
<conditions>
<propertyFilter property="hobby" enabled="true" operation="STARTS_WITH"/>
</conditions>
</genericFilter>
configurations
Содержит объявление конфигураций времени разработки.
properties
Определяет, какие атрибуты сущности можно добавлять в условие. Этот элемент имеет следующие атрибуты:
-
include- указывает регулярное выражение. Атрибуты сущности, соответствующие этому выражению, включаются. -
exclude- указывает регулярное выражение. Атрибуты сущности, соответствующие этому выражению, исключаются. -
excludeProperties- указывает разделённый запятыми список имён атрибутов или путей к ним, которые следует исключить. Например:customer.name. -
excludeRecursively- определяет, должен ли атрибут изexcludePropertiesбыть рекурсивно исключён для всего графа сущностей. Если указаноtrue, дочерние атрибуты исключённого атрибута также исключаются.
Пример:
<genericFilter id="filterWithProperties" dataLoader="customerDl">
<properties include=".*"
exclude="(hobby)|(age)"
excludeProperties="id"
excludeRecursively="true"/>
</genericFilter>
|
Вы можете включать и исключать свойства коллекции ( |
|
Вы можете включать и исключать динамические атрибуты в качестве условия фильтрации. Это не требует фасета dynamicAttributes в этом экране. Укажите код атрибута с префиксом "+":
Если такой атрибут имеет тип сущности, его вложенные атрибуты нельзя использовать в условии фильтрации. |
Следующие атрибуты сущности игнорируются:
-
Недоступные из-за разрешений безопасности
-
Неперсистентные атрибуты
-
Атрибуты, аннотированные
@SystemLevel -
Атрибуты типа
byte[]
responsiveSteps
Определяет количество столбцов для отображения условий поиска в зависимости от доступного места. По умолчанию условия поиска располагаются в два столбца и перестраиваются в один столбец, когда ширина макета становится меньше.
Следующий фильтр переопределяет поведение по умолчанию, чтобы настроить макет на один, два или три столбца с надписями, расположенными сверху:
<layout>
<genericFilter dataLoader="customerDl">
<responsiveSteps>
<responsiveStep minWidth="0" columns="1"/>
<responsiveStep minWidth="30em" columns="2"/>
<responsiveStep minWidth="50em" columns="3" labelsPosition="TOP"/>
</responsiveSteps>
</genericFilter>
</layout>