Filter 过滤器
基本用法
Filter
需要连接到一个独立的 CollectionContainer
或 KeyValueCollectionContainer
中定义的数据加载器。过滤器生成一个 Condition
对象,后续加载器使用这个条件从 数据存储 加载数据。对于 JPA 实体,数据存储会修改生成的 JPQL 查询语句,因此数据过滤是在数据库级别完成的,从数据库仅加载了过滤后的数据至应用程序内存。
默认情况下,Jmix Studio 创建实体浏览界面和主从界面时会生成 Filter
组件。
在 XML 描述中声明 filter
的例子如下:
<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
浏览界面创建多条件的快速过滤器。 -
保存该过滤器以便将来使用。
创建快速过滤
-
点击 Add search condition(添加搜索条件) 链接(1)。
-
在 Properties(属性) 列表中选择 Age 属性。
-
选择 Hobby 属性。
选择的条件在过滤器面板顶部展示。
-
修改条件值字段和运算符:
增加条件
如需创建一个快速过滤器,点击 Add search condition(添加搜索条件) 链接(1),会显示 Add condition(添加条件) 的界面:
下列是可用的过滤条件类型:
-
Properties(属性) - 实体和关联实体的属性,条件树展示持久化和 动态 实体属性。这些属性按照 properties 元素定义的规则展示。
-
Predefined conditions(预定义条件) 是开发者在 XML 描述的 conditions 元素中定义的条件。预定义条件最初不会添加至任何配置中,用户可以在 Add Condition(添加条件) 界面选择并添加至 运行时配置。
-
Configurations(过滤器配置) 可以在设计时或运行时创建(通过 配置编辑器)。
选中的过滤条件会在过滤器区域顶部显示。这个 条件删除图标会在每个条件的旁边显示,允许删除已选择的条件。
因此用户有机会再运行时创建过滤器条件。
属性条件
Property conditions editor(属性条件编辑器) 支持用户配置 PropertyFilter 组件的属性。PropertyFilter
与实体属性相关。
在 Property(属性) 字段选择实体属性。
Operation(运算符) 字段支持选择条件的 运算符。根据属性类型不同运算符也不同。
Parameter name(参数名) 属性用于设置查询参数的名称。可以用该名称引入配置中过滤器的相互依赖。如果未定义,则参数名随机生成。
可以在 Caption(标题) 字段设置属性过滤器条件的自定义标题。
用 Operation editable(运算符可编辑) 复选框设置是否显示运算符选择器。如果勾选,则支持在运行时选择条件运算符。
用 Operation caption visible(运算符标题可见) 复选框定义运算符文本的可见性。
可以在 Default value(默认值) 字段设置过滤条件的默认值。
JPQL 条件
JPQL conditions editor(JPQL 条件编辑器) 支持用户创建基于 JPQL 表达式的条件。
Parameter type(参数类型) 字段,选择条件参数的 Java 类。No parameter
值支持创建无参数的条件。示例:
Caption(标题) 字段必需。设置过滤器中该条件的显示名称。
用 Parameter name(参数名) 属性设置关联的查询语句参数的名称。可以用该名称引入配置中过滤器的相互依赖。如果未定义,则参数名随机生成。
用 Has IN expression(有 IN 表达式) 复选框定义 JPQL 表达式是否需要包含 IN
表达式。如果勾选,应用程序会使用 ValuesPicker 组件创建条件值列表。
可以在 Default value(默认值) 字段设置过滤条件的默认值。
Join 字段支持指定一个 JQPL 表达式,该表达式会被添加在数据加载器查询语句的 from
部分。如果要依赖关联实体集合的属性来创建一个复杂的过滤条件,可以用这个属性。这个属性值应该以 join
和 left join
语句开头。表达式中用 {E}
占位符表示选择实体,而非实体的别名。
Where 字段支持指定一个 JQPL 表达式,该表达式会被添加在数据加载器查询语句的 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
是配置的根元素。
配置不会存储所有组件的引用,而只保存至根元素的引用,从根元素可以获取其他过滤器组件。
配置可以在设计时或运行时通过 运行时配置编辑器 创建。
设计时配置
设计时的配置不能在运行时修改。但是,用户仍然可以用 Copy
操作将设计时配置的所有条件复制到运行时的配置中。
所有设计时配置都与保存的过滤器和配置一起在下拉菜单(2)中展示。
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
将作为 消息包 中的键值。
用 default
XML 属性为过滤器设置默认的设计时配置。界面打开时自动展示。
如需在 Jmix Studio 中添加设计时配置,可以在界面 XML 或者 Component Hierarchy 面板中选择 |
运行时配置
如需在运行时创建、编辑或删除配置,用户需要有 ui.filter.modifyConfiguration 许可。
用配置(6)中的 Edit(编辑) 操作打开 Configuration editor(配置编辑器)。
Configuration name(配置名称) 字段必需。配置名称与保存的过滤器和配置一起在下拉菜单(2)中展示。
用 Available for all users(所有用户可用) 复选框设置所有用户都能使用。有 ui.filter.modifyGlobalConfiguration 特殊权限的用户才能使用该复选框。
用 Default for all users(所有用户默认) 复选框设置当用户打开界面时,是否默认选择创建的配置。仅在 Available for all users(所有用户可用) 勾选时可用。
Configuration editor(配置编辑器) 的其他字段在 组合条件 中介绍。
过滤器元素
XML 中定义的 filter
可以包含内部元素。用于定义用户在 Add Condition(添加条件) 窗口中可选择的条件:
属性
properties
元素可以配置多个实体属性用于选择。该元素有下列属性:
-
include
必带属性。包含一个正则表达式,能匹配实体的属性名称。
-
exclude
- 包含一个正则表达式,如果实体属性能匹配此项,那么会从之前的include
配置中排除掉。 -
excludeProperties
- 包含一个英文逗号分隔的应该被排除掉的属性路径列表。跟之前的exclude
不同,这里支持遍历实体关系图,比如customer.name
。 -
excludeRecursively
- 设置excludeProperties
里面定义的属性是否需要递归的排除掉。如果设置的true
,那么属性和它的嵌套属性,只要是相同名称的,都会被排除掉。
下面的例子中,我们声明带有 properties
内部元素的 filter
组件:
<filter id="filterWithProperties"
dataLoader="customersDl">
<properties include=".*"
exclude="(hobby)|(age)"
excludeProperties="id"
excludeRecursively="true"/>
</filter>
使用
界面中不需要有 dynamicAttributes facet。 注意,如果动态属性是一个实体,则该实体内部的属性无法用来进行过滤。 |
使用 properties
时,实体的下列属性会被忽略:
-
由于 安全许可 限制而不能访问的属性。
-
集合属性(
@OneToMany
、@ManyToMany
)。 -
非持久化属性。
-
使用
@SystemLevel
注解的属性。 -
byte[]
类型的属性。
conditions
conditions
元素用来创建 预定义条件。
下面的例子中,我们声明带有 conditions
内部元素的 filter
组件:
<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。
如需在 Jmix Studio 中添加 |
configurations
configurations
元素用来创建 设计时配置。
actions
actions
- 可选元素,定义过滤器管理的操作列表。
框架在过滤器设置按钮(6) 中提供下列默认操作:
-
Save(保存) - 由
FilterSaveAction
实现(XML 中type="filter_save"
),保存对过滤器的修改至当前配置。
-
Save with values(带值保存) - 由
FilterSaveWithValuesAction
实现(XML 中type="filter_saveWithValues"
),保存对过滤器的修改至当前配置,且使用条件字段(5)中的值作为过滤器的默认值。
-
Save as(另存为) - 由
FilterSaveAsAction
实现(XML 中type="filter_saveAs"
),将过滤器配置另存为新名称。
-
Remove(删除) - 由
FilterRemoveAction
实现(XML 中type="filter_remove"
),删除当前运行时过滤器配置。对 设计时配置 禁用。
-
Make default(设为默认) - 由
FilterMakeDefaultAction
实现(XML 中type="filter_makeDefault"
),将过滤器配置设置成界面默认。当界面打开时,这个过滤器会自动显示在过滤器区域。优先于设计时配置的 default 属性和运行时勾选的 Default for all users((所有用户默认))。如果界面未添加screenSettings
facet,则该功能不可用。
-
Copy(复制) - 由
FilterCopyAction
实现(XML 中type="filter_copy"
),将设计时配置的所有条件复制到运行时配置。
-
Clear values(清空值) - 由
FilterClearValuesAction
实现(XML 中type="filter_clearValues"
),清空过滤器条件值(5)。
-
Add(添加) 由
FilterAddConditionAction
实现(XML 中type="filter_addCondition"
),为当前过滤器配置增加条件。
用户可以用内部的 actions
元素覆盖 默认 操作。示例:
<filter id="filterWithActions"
dataLoader="customersDl">
<properties include=".*"/>
<actions>
<action id="addCondition" type="filter_addCondition"/>
<action id="clearValues" type="filter_clearValues"/>
</actions>
</filter>
如需在 Jmix Studio 中添加 |
可以用 action
元素的 XML 属性配置通用的操作参数,参阅 Actions 了解详情。
过滤器属性
autoApply
autoApply
属性指定过滤器的应用时机。如果属性为 false
,过滤器只有在每次点击 Refresh(刷新) 按钮时应用。如果属性为 true
,则每次修改过滤器组件时会自动应用。默认值通过 jmix.ui.component.filter-auto-apply 属性定义。
columnsCount
columnsCount
设置一行显示的列数。默认值在 jmix.ui.component.filter-columns-count 属性设置。
权限许可
过滤器的高级管理功能需要特定的许可:
-
如需新建、修改、删除过滤器 配置,用户需要有
ui.filter.modifyConfiguration
特殊权限。
-
如需新建、修改、删除全局(available for all users(所有用户可用))过滤器配置,用户需要有
ui.filter.modifyGlobalConfiguration
特殊权限。
-
如需新建、修改运行时 JPQL 条件,用户需要有
ui.filter.modifyJpqlCondition
特殊权限。
可以直接给用户设置预定义的 UI: edit filters 资源角色,或自定义 角色 配置需要的权限许可。
应用程序属性
下列应用程序属性影响过滤器行为:
在过滤器条件中选取实体的组件可以使用 jmix.ui.component.entity-field-type 和 jmix.ui.component.entity-field-actions 属性定义。
编程式创建过滤器
下面示例中,我们将创建一个带 设计时配置 的 Filter
组件并将该组件添加至 XML 描述定义的标签页中。
用 UiComponents
工厂在控制器中创建 Filter
组件。
@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;
@Subscribe
protected void onAfterInit(AfterInitEvent event) {
Filter filter = uiComponents.create(Filter.NAME); (1)
filter.setId("programmaticFilter");
filter.setDataLoader(customersDl);
filter.loadConfigurationsAndApplyDefault();
DesignTimeConfiguration javaDefaultConfiguration =
filter.addConfiguration("javaDefaultConfiguration",
"Default configuration"); (2)
PropertyFilter<Integer> agePropertyFilter =
uiComponents.create(PropertyFilter.NAME); (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)
VBoxLayout tab = (VBoxLayout) getWindow()
.getComponentNN("programmaticFilterTab"); (7)
tab.add(filter); (8)
}
1 | 创建 Filter 并设置其属性。 |
2 | 添加设计时配置,id 为 javaDefaultConfiguration ,名称为 Default configuration 。 |
3 | 创建 PropertyFilter 并设置其属性。 |
4 | 通过给定的 metaClass、实体属性和运算符生成过滤器值组件。 |
5 | 将创建的属性过滤器添加至 javaDefaultConfiguration 配置。 |
6 | 设置当前配置为 javaDefaultConfiguration 配置。 |
7 | 通过 id 获取标签页。 |
8 | 将创建的 Filter 组件添加至 programmaticFilterTab 标签页。 |
事件和处理器
如需使用 Jmix Studio 生成处理器的桩代码,需要在界面 XML 描述或者 Jmix UI 层级结构面板选中该组件,然后用 Jmix UI 组件面板的 Handlers 标签页生成。 或者可以使用界面控制器顶部面板的 Generate Handler 按钮。 |
ConfigurationChangeEvent
ConfigurationChangeEvent
当 配置 修改后发送。下面例子展示订阅 filter
的该事件:
@Subscribe("filter")
public void onFilterConfigurationChange(Filter.ConfigurationChangeEvent event) {
notifications.create()
.withCaption("Before: " + event.getPreviousConfiguration().getName() +
". After: " + event.getNewConfiguration().getName())
.show();
}
如需以编程的方式注册事件处理器,使用组件的 addConfigurationChangeListener()
方法。
PropertiesFilterPredicate
@Install(to = "filter", subject = "propertiesFilterPredicate")
private boolean filterPropertiesFilterPredicate(MetaPropertyPath metaPropertyPath) {
return !metaPropertyPath.getMetaProperty().getName().equals("hobby");
}
这个判断被添加到当前的属性过滤判断中,并测试具有给定路径的属性是否可用于过滤。
如需以编程的方式添加判断,使用组件的 addPropertiesFilterPredicate()
方法。生成的判断是一个组合判断,由给定的判断和当前属性过滤的判断一起组成一个 AND 条件。
XML 属性
可以使用 Studio 界面设计器的 Jmix UI 组件面板查看和编辑组件的属性。 |
Filter XML 属性
align - autoApply - caption - captionAsHtml - captionPosition - collapsable - collapsed - colspan - columnsCount - contextHelpText - contextHelpTextHtmlEnabled - css - description - descriptionAsHtml - enable - box.expandRatio - height - htmlSanitizerEnabled - icon - id - margin - responsive - rowspan - stylename - visible - width