过滤器组件
PropertyFilter
PropertyFilter - 属性过滤器
组件可以用在 Filter
组件内或单独使用。
下面例子演示了如何使用 XML 描述中的 PropertyFilter
创建设计时配置:
<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"
id="filterPropertyFilter"
caption="PropertyFilter variations">
<properties include=".*"/>
<configurations>
<configuration id="propertyConfiguration"
default="true"
name="PropertyFilter">
<propertyFilter property="age"
operation="GREATER_OR_EQUAL"
operationEditable="true"/>
</configuration>
</configurations>
</filter>
</layout>
如需在 Jmix Studio 中添加 |
还可以在界面控制器类中创建设计时配置:
@Autowired
protected UiComponents uiComponents;
@Autowired
protected SingleFilterSupport singleFilterSupport;
@Autowired
protected Filter pfdtcFilter;
@Autowired
protected Filter jfdtcFilter;
@Autowired
protected JpqlFilterSupport jpqlFilterSupport;
@Autowired
protected Filter gfdtcFilter;
@Subscribe
protected void onInit(InitEvent event) {
DesignTimeConfiguration javaDefaultConfigurationPF =
pfdtcFilter.addConfiguration("javaDefaultConfiguration",
"Default configuration"); (1)
DataLoader dataLoaderPF = pfdtcFilter.getDataLoader();
PropertyFilter<City> cityPropertyFilter =
uiComponents.create(PropertyFilter.NAME); (2)
cityPropertyFilter.setConditionModificationDelegated(true);
cityPropertyFilter.setDataLoader(dataLoaderPF);
cityPropertyFilter.setProperty("city");
cityPropertyFilter.setOperation(PropertyFilter.Operation.EQUAL);
cityPropertyFilter.setOperationEditable(true);
cityPropertyFilter.setParameterName(PropertyConditionUtils.generateParameterName(
cityPropertyFilter.getProperty()));
cityPropertyFilter.setValueComponent(singleFilterSupport.generateValueComponent(
dataLoaderPF.getContainer().getEntityMetaClass(),
cityPropertyFilter.getProperty(),
cityPropertyFilter.getOperation())); (3)
javaDefaultConfigurationPF.getRootLogicalFilterComponent()
.add(cityPropertyFilter); (4)
PropertyFilter<Level> levelPropertyFilter =
uiComponents.create(PropertyFilter.NAME);
levelPropertyFilter.setConditionModificationDelegated(true);
levelPropertyFilter.setDataLoader(dataLoaderPF);
levelPropertyFilter.setProperty("level");
levelPropertyFilter.setOperation(PropertyFilter.Operation.EQUAL);
levelPropertyFilter.setOperationEditable(true);
levelPropertyFilter.setParameterName(PropertyConditionUtils.generateParameterName(
levelPropertyFilter.getProperty()));
levelPropertyFilter.setValueComponent(singleFilterSupport.generateValueComponent(
dataLoaderPF.getContainer().getEntityMetaClass(),
levelPropertyFilter.getProperty(),
levelPropertyFilter.getOperation()
));
javaDefaultConfigurationPF.getRootLogicalFilterComponent().add(levelPropertyFilter);
pfdtcFilter.setCurrentConfiguration(javaDefaultConfigurationPF); (5)
}
1 | 添加一个设计时配置,id 为 javaDefaultConfiguration ,名称为 Default configuration 。 |
2 | 创建 PropertyFilter 组件,并设置其属性。 |
3 | 通过给定的 metaClass、实体属性和运算符生成过滤器值组件。 |
4 | 将创建的属性过滤器添加至 javaDefaultConfiguration 配置中。 |
5 | 将 javaDefaultConfiguration 设置为当前配置。 |
更多信息请参阅 PropertyFilter。
JpqlFilter
JpqlFilter - JPQL 过滤器
是一个 UI 组件,用于过滤从 DataLoader
返回的实体。组件包含 JPQL 表达式,表达式会被添加在数据加载器查询语句的 from
和 where
部分。设置条件的布局由组件自动完成。一个 JpqlFilter
布局一般包含一个标题和一个用于编辑条件值的字段。该组件只能用在 Filter
组件内部。
下面示例演示如何使用 JpqlFilter
创建设计时配置:
<window xmlns="http://jmix.io/schema/ui/window"
caption="msg://filterScreen.caption"
xmlns:c="http://jmix.io/schema/ui/jpql-condition"> (1)
<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 id="filterJpqlFilter"
dataLoader="customersDl"
caption="JpqlFilter variations">
<properties include=".*"/>
<configurations>
<configuration id="jpqlConfiguration"
default="true"
name="JpqlFilter">
<jpqlFilter caption="Name like"
parameterClass="java.lang.String">
<condition>
<c:jpql>
<c:where>{E}.firstName like ?</c:where> (2)
</c:jpql>
</condition>
</jpqlFilter>
</configuration>
</configurations>
</filter>
</layout>
</window>
1 | 需要添加 JPQL 条件命名空间 |
2 | 定义一个 JPQL 条件,join 元素可选,where 元素必需。 |
配置 JPQL 条件,需在 jpqlFilter
内定义 condition
元素,内部可使用必需的 where 元素和可选的 join 元素。下面例子中,使用 join
和 where
元素创建 jpqlFilter
:
<filter id="filterJpqlFilter"
dataLoader="customersDl"
caption="JpqlFilter variations">
<properties include=".*"/>
<configurations>
<configuration id="jpqlConfigurationWithJoin"
name="JpqlFilter with Join">
<jpqlFilter caption="Customers with brand"
parameterClass="ui.ex1.entity.Brand">
<condition>
<c:jpql>
<c:join>join {E}.favouriteBrands i</c:join>
<c:where>i.id = ?</c:where>
</c:jpql>
</condition>
</jpqlFilter>
</configuration>
</configurations>
</filter>
filter
组件内部的 jpqlFilter
属性设置要点:
-
用
defaultValue
属性设置过滤器条件的默认值。
-
如果 JPQL 表达式包含
in (?)
条件,则hasInExpression
属性应该设置为true
。此时,应用程序会使用 ValuesPicker 组件,以便用户能输入多个条件参数值。下面是使用
hasInExpression
属性的jpqlFilter
示例:<filter id="filterJpqlFilter" dataLoader="customersDl" caption="JpqlFilter variations"> <properties include=".*"/> <configurations> <configuration id="jpqlConfigurationInExpr" name="JpqlFilter with IN expression"> <jpqlFilter caption="City in" parameterClass="ui.ex1.entity.City" hasInExpression="true"> <condition> <c:jpql> <c:where>{E}.city in ?</c:where> </c:jpql> </condition> </jpqlFilter> </configuration> </configurations> </filter>
-
parameterClass
必需属性;指定条件参数的 Java 类。
-
parameterName
- 查询语句中关联的参数名。可以用该名称引入配置中过滤器的相互依赖。如果未定义,则参数名随机生成。
如需在 Jmix Studio 中添加 |
还可以在界面控制器类中创建设计时配置:
@Autowired
protected UiComponents uiComponents;
@Autowired
protected SingleFilterSupport singleFilterSupport;
@Autowired
protected Filter pfdtcFilter;
@Autowired
protected Filter jfdtcFilter;
@Autowired
protected JpqlFilterSupport jpqlFilterSupport;
@Autowired
protected Filter gfdtcFilter;
@Subscribe
protected void onInit(InitEvent event) {
DesignTimeConfiguration javaDefaultConfigurationJF =
jfdtcFilter.addConfiguration("javaDefaultConfiguration",
"Default configuration"); (1)
DataLoader dataLoaderJF = jfdtcFilter.getDataLoader();
JpqlFilter<Brand> jpqlFilter =
uiComponents.create(JpqlFilter.NAME); (2)
jpqlFilter.setFrame(getWindow());
jpqlFilter.setConditionModificationDelegated(true);
jpqlFilter.setDataLoader(dataLoaderJF);
jpqlFilter.setCondition("i.id = ?", "join {E}.favouriteBrands i");
jpqlFilter.setParameterClass(Brand.class);
jpqlFilter.setCaption("Select the brand");
jpqlFilter.setParameterName(jpqlFilterSupport.generateParameterName(
jpqlFilter.getId(),
jpqlFilter.getParameterClass().getSimpleName()));
jpqlFilter.setValueComponent(singleFilterSupport.generateValueComponent(
dataLoaderJF.getContainer().getEntityMetaClass(),
jpqlFilter.hasInExpression(),
jpqlFilter.getParameterClass())); (3)
javaDefaultConfigurationJF.getRootLogicalFilterComponent()
.add(jpqlFilter); (4)
jfdtcFilter.setCurrentConfiguration(javaDefaultConfigurationJF); (5)
}
1 | 添加一个设计时配置,id 为 javaDefaultConfiguration ,名称为 Default configuration 。 |
2 | 创建 JpqlFilter 组件,并设置其属性。 |
3 | 通过给定的 metaClass 和值类型生成过滤器值组件。 |
4 | 将创建的 jpql 过滤器添加至 javaDefaultConfiguration 配置中。 |
5 | 将 javaDefaultConfiguration 设置为当前配置。 |
无参数过滤器
也可以定义没有参数的查询语句。设置 parameterClass
的值为 java.lang.Void
,并使用 java.lang.Boolean
作为值:
-
true
表示where
和join
的 JPQL 语句会添加至数据加载器的查询语句中。 -
false
则不会加载where
和join
中的语句。
示例:
<filter id="parameterlessFilter"
dataLoader="customersDl"
caption="JPQL Filter without Parameters">
<properties include=".*"/>
<configurations>
<configuration id="jpqlConfigurationNoParams"
name="JPQL Filter without Parameters">
<jpqlFilter caption="Customers from London"
parameterClass="java.lang.Void"
defaultValue="true"> (1)
<condition>
<c:jpql>
<c:join>join {E}.city c</c:join> (2)
<c:where>c.name = 'London'</c:where>
</c:jpql>
</condition>
</jpqlFilter>
</configuration>
</configurations>
</filter>
1 | parameterClass="java.lang.Void" 表示过滤器无参数,defaultValue="true" 表示默认会将 where 和 join 表达式会添加至数据加载器的查询语句中 |
2 | 定义 JPQL 条件,使用可选的 join 元素和必要的 where 元素。 |
下面是在界面控制器中创建无参数 JPQL 过滤器的示例:
@Autowired
private Filter parameterlessFilter;
@Subscribe
protected void onInit(InitEvent event) {
DesignTimeConfiguration javaConfiguration = parameterlessFilter
.addConfiguration("javaConfiguration", "Java configuration");
DataLoader dataLoader = parameterlessFilter.getDataLoader();
JpqlFilter<Boolean> jpqlFilterNoParams = uiComponents.create(JpqlFilter.NAME);
jpqlFilterNoParams.setFrame(getWindow());
jpqlFilterNoParams.setConditionModificationDelegated(true);
jpqlFilterNoParams.setDataLoader(dataLoader);
jpqlFilterNoParams.setCondition("{E}.age > 21", null);
jpqlFilterNoParams.setParameterClass(Void.class);
jpqlFilterNoParams.setCaption("Customer's age > 21");
jpqlFilterNoParams.setParameterName(jpqlFilterSupport
.generateParameterName(jpqlFilterNoParams.getId(),
jpqlFilterNoParams.getParameterClass().getSimpleName()));
jpqlFilterNoParams.setValueComponent(singleFilterSupport
.generateValueComponent(dataLoader.getContainer().getEntityMetaClass(),
jpqlFilterNoParams.hasInExpression(),
jpqlFilterNoParams.getParameterClass()
));
jpqlFilterNoParams.setValue(true);
javaConfiguration.setFilterComponentDefaultValue(
jpqlFilterNoParams.getParameterName(),
jpqlFilterNoParams.getValue());
javaConfiguration.getRootLogicalFilterComponent().add(jpqlFilterNoParams);
jpqlFilterNoParams.setValue(true);
javaConfiguration.setFilterComponentDefaultValue(
jpqlFilterNoParams.getParameterName(),
jpqlFilterNoParams.getValue());
javaConfiguration.getRootLogicalFilterComponent().add(jpqlFilterNoParams);
}
无参数的 JPQL 过滤器配置也可以在运行时创建:
GroupFilter
GroupFilter - 组合条件过滤器
组件是一个组合组件,用带有 ResponsiveGridLayout 的 GroupBoxLayout 作为根布局容器。该组件用在需要将多个条件组合成一个逻辑组时(使用逻辑运算符 AND
或 OR
)。组件只能在 Filter
组件内部使用。
下面示例演示如何使用 GroupFilter
创建设计时配置:
<filter id="filterGroupFilter"
dataLoader="customersDl"
caption="GroupFilter variations">
<properties include=".*"/>
<configurations>
<configuration id="groupFilter"
name="Simple groupFilter"
default="true">
<groupFilter operation="OR">
<propertyFilter property="age"
operation="GREATER_OR_EQUAL"
operationEditable="true"/>
<propertyFilter property="city"
operation="EQUAL"
operationEditable="true"/>
</groupFilter>
</configuration>
</configurations>
</filter>
operation
属性必需。可以用两个逻辑运算符:
-
AND
是默认运算符 -
OR
如需在 Jmix Studio 中添加 |
也可以在界面控制器中创建设计时配置:
@Autowired
protected UiComponents uiComponents;
@Autowired
protected SingleFilterSupport singleFilterSupport;
@Autowired
protected Filter pfdtcFilter;
@Autowired
protected Filter jfdtcFilter;
@Autowired
protected JpqlFilterSupport jpqlFilterSupport;
@Autowired
protected Filter gfdtcFilter;
@Subscribe
protected void onInit(InitEvent event) {
DesignTimeConfiguration javaDefaultConfigurationGF =
gfdtcFilter.addConfiguration("javaDefaultConfiguration",
"Default configuration"); (1)
DataLoader dataLoaderGF = gfdtcFilter.getDataLoader();
GroupFilter groupFilter =
uiComponents.create(GroupFilter.NAME); (2)
groupFilter.setConditionModificationDelegated(true);
groupFilter.setDataLoader(dataLoaderGF);
groupFilter.setOperation(LogicalFilterComponent.Operation.OR); (3)
PropertyFilter<Integer> pointsPropertyFilter =
uiComponents.create(PropertyFilter.NAME); (4)
pointsPropertyFilter.setConditionModificationDelegated(true);
pointsPropertyFilter.setDataLoader(dataLoaderGF);
pointsPropertyFilter.setProperty("rewardPoints");
pointsPropertyFilter.setOperation(PropertyFilter.Operation.GREATER_OR_EQUAL);
pointsPropertyFilter.setOperationEditable(true);
pointsPropertyFilter.setParameterName(PropertyConditionUtils
.generateParameterName(pointsPropertyFilter.getProperty()));
pointsPropertyFilter.setValueComponent(singleFilterSupport.generateValueComponent(
dataLoaderGF.getContainer().getEntityMetaClass(),
pointsPropertyFilter.getProperty(),
pointsPropertyFilter.getOperation()));
groupFilter.add(pointsPropertyFilter); (5)
PropertyFilter<Hobby> hobbyPropertyFilter =
uiComponents.create(PropertyFilter.NAME);
hobbyPropertyFilter.setConditionModificationDelegated(true);
hobbyPropertyFilter.setDataLoader(dataLoaderGF);
hobbyPropertyFilter.setProperty("hobby");
hobbyPropertyFilter.setOperation(PropertyFilter.Operation.EQUAL);
hobbyPropertyFilter.setOperationEditable(true);
hobbyPropertyFilter.setParameterName(PropertyConditionUtils.generateParameterName(
hobbyPropertyFilter.getProperty()));
hobbyPropertyFilter.setValueComponent(singleFilterSupport.generateValueComponent(
dataLoaderGF.getContainer().getEntityMetaClass(),
hobbyPropertyFilter.getProperty(),
hobbyPropertyFilter.getOperation()
));
groupFilter.add(hobbyPropertyFilter); (6)
javaDefaultConfigurationGF.getRootLogicalFilterComponent().add(groupFilter); (7)
PropertyFilter<Integer> agePropertyFilter =
uiComponents.create(PropertyFilter.NAME);
agePropertyFilter.setConditionModificationDelegated(true);
agePropertyFilter.setDataLoader(dataLoaderGF);
agePropertyFilter.setProperty("age");
agePropertyFilter.setOperation(PropertyFilter.Operation.GREATER_OR_EQUAL);
agePropertyFilter.setOperationEditable(true);
agePropertyFilter.setParameterName(PropertyConditionUtils.generateParameterName(
agePropertyFilter.getProperty()));
agePropertyFilter.setValueComponent(singleFilterSupport.generateValueComponent(
dataLoaderGF.getContainer().getEntityMetaClass(),
agePropertyFilter.getProperty(),
agePropertyFilter.getOperation()
));
javaDefaultConfigurationGF.getRootLogicalFilterComponent().add(agePropertyFilter);
pointsPropertyFilter.setValue(1000);
javaDefaultConfigurationGF.setFilterComponentDefaultValue(
pointsPropertyFilter.getParameterName(), 1000); (8)
hobbyPropertyFilter.setValue(Hobby.FISHING);
javaDefaultConfigurationGF.setFilterComponentDefaultValue(
hobbyPropertyFilter.getParameterName(), Hobby.FISHING);
agePropertyFilter.setValue(30);
javaDefaultConfigurationGF.setFilterComponentDefaultValue(
agePropertyFilter.getParameterName(), 30);
}
1 | 添加一个设计时配置,id 为 javaDefaultConfiguration ,名称为 Default configuration 。 |
2 | 创建 GroupFilter 组件,并设置其属性。 |
3 | 为 groupFilter 设置 OR 逻辑运算符。 |
4 | 创建 PropertyFilter 组件,并设置其属性。 |
5 | 添加 pointsPropertyFilter 至 groupFilter 。 |
6 | 添加 hobbyPropertyFilter 至 groupFilter 。 |
7 | 将创建的组过滤器添加至 javaDefaultConfiguration 配置。 |
8 | 通过参数名为 javaDefaultConfiguration 配置设置 pointsPropertyFilter 的默认值。 |
注册过滤器组件
如需创建并注册 UI 过滤器组件,需要以下对象:
-
一个组件类 - UI 组件,展示在
Filter
组件内。组件类需要继承FilterComponent
类。参考PropertyFilter
类作为示例。 -
一个模型类 - 非持久化类,保存过滤器组件的状态。模型类用来保存过滤器组件状态至数据库并在运行时展示和修改过滤器组件。模型类需要继承
FilterCondition
类。参考PropertyFilterCondition
类作为示例。 -
一个转换器类 - 在组件和模型之间转换。转换器类需实现
FilterConverter
接口。 -
一个编辑界面 - 模型编辑界面。如果为指定标识符,则使用默认的标识符(例如,
modelName.edit
、PropertyFilterCondition.edit
)。
PropertyFilter
注册示例:
@Bean
public FilterComponentRegistration registerPropertyFilter() {
return FilterComponentRegistrationBuilder.create(PropertyFilter.class,
PropertyFilterCondition.class,
PropertyFilterConverter.class)
.withEditScreenId("ui_PropertyFilterCondition.edit")
.build();
}
所有注册的过滤器组件都在 Add Condition(添加条件)
对话框的 弹窗按钮 中显示。
可以替换 Jmix 框架中注册的过滤器组件为自定义的组件,只需在 FilterComponentRegistration
bean 使用 @Order
注解(例如,需要增加过滤器保存的模型属性集合时)。
XML 属性
可以使用 Studio 界面设计器的 Jmix UI 组件面板查看和编辑组件的属性。 |
JpqlFilter XML 属性
align - caption - captionAsHtml - colspan - contextHelpText - contextHelpTextHtmlEnabled - css - defaultValue - description - descriptionAsHtml - editable - enable - box.expandRatio - hasInExpression - height - htmlSanitizerEnabled - icon - id - parameterClass - parameterName - required - requiredMessage - responsive - rowspan - stylename - tabIndex - visible - width
GroupFilter XML 属性
align - caption - captionAsHtml - colspan - description - descriptionAsHtml - enable - box.expandRatio - height - htmlSanitizerEnabled - icon - id - operation - operationCaptionVisible - responsive - rowspan - stylename - visible - width