genericFilter 的组件

genericFilter 的一些固定配置可以在 运行时设计时 进行配置。本章提供设计时 genericFilter 的配置说明,包含三种预定义的过滤器组件:

框架支持自定义过滤器组件,并在 genericFilter 中使用。参阅 注册过滤器组件 章节。

propertyFilter

propertyFilter - 属性过滤器 可以基于实体的特定属性添加过滤条件。

该组件也可以单独使用。参阅 propertyFilter 属性过滤器

本节的声明式和编程式配置都可以在视图中创建如下过滤器:

generic filter components property filter

声明式配置

genericFilter 的配置可以在视图的 XML 文件中声明式指定。以下示例展示如何配置 propertyFilter

<layout>
    <genericFilter dataLoader="customerDl"
                   id="genericFilterProperty"> (1)
        <properties include=".*"/>
        <configurations>
            <configuration id="propertyConfiguration"
                           default="true"
                           name="PropertyFilter">
                <propertyFilter property="age"
                                operation="GREATER_OR_EQUAL"
                                operationEditable="true"/> (2)
            </configuration>
        </configurations>
    </genericFilter>
</layout>
1 genericFilter 组件的绑定了数据加载器。
2 propertyFilter 根据 age 属性配置了一个过滤条件。

编程式配置

另一种定义的方式是在视图控制器中编程式配置:

@Autowired
private UiComponents uiComponents;

@ViewComponent
private GenericFilter pfdtcGenericFilter;

@Autowired
private SingleFilterSupport singleFilterSupport;

@Subscribe
public void onInit(final InitEvent event) {
    DesignTimeConfiguration javaDefaultConfigurationPF =
            pfdtcGenericFilter.addConfiguration("javaDefaultConfiguration",
                    "PropertyFilter configuration"); (1)
    DataLoader dataLoaderPF = pfdtcGenericFilter.getDataLoader();

    PropertyFilter<Integer> agePropertyFilter =
            uiComponents.create(PropertyFilter.class); (2)
    agePropertyFilter.setConditionModificationDelegated(true);
    agePropertyFilter.setDataLoader(dataLoaderPF);
    agePropertyFilter.setProperty("age");
    agePropertyFilter.setOperation(PropertyFilter.Operation.GREATER_OR_EQUAL);
    agePropertyFilter.setOperationEditable(true);
    agePropertyFilter.setParameterName(PropertyConditionUtils.generateParameterName(
            agePropertyFilter.getProperty()));
    agePropertyFilter.setValueComponent(singleFilterSupport.generateValueComponent(
            dataLoaderPF.getContainer().getEntityMetaClass(),
            agePropertyFilter.getProperty(),
            agePropertyFilter.getOperation())); (3)
    javaDefaultConfigurationPF.getRootLogicalFilterComponent()
            .add(agePropertyFilter); (4)

    pfdtcGenericFilter.setCurrentConfiguration(javaDefaultConfigurationPF); (5)
}
1 添加一个设计时配置。方法接收两个参数:配置id和配置名。
2 创建一个 PropertyFilter 实例并设置其属性。
3 基于 metaClass、属性和运算符为该过滤器创建一个组件。
4 将过滤器添加至配置中。LogicalFilterComponent 是配置的根元素。
5 设置为当前配置。

jpqlFilter

jpqlFilter - JPQL 过滤器 支持使用 JPQL 查询进行过滤。原理是修改数据加载器的查询语句,添加可选的 join 和必需的 where 子句,实现对查询结果的修改。

本节的声明式和编程式配置都可以在视图中创建如下过滤器:

generic filter jpql filter

声明式配置

A genericFilter configuration can be specified declaratively, inside the XML view descriptor. See the following example for configuration with jpqlFilter:

<layout>
    <genericFilter dataLoader="customerDl"
                   id="genericFilterJpql"> (1)
        <properties include=".*"/>
        <configurations>
            <configuration id="jpqlConfiguration"
                           default="true"
                           name="JpqlFilter">
                <jpqlFilter parameterClass="java.lang.String"
                            label="City name is">
                    <condition>
                        <jpql>
                            <join>join {E}.city c</join> (2)
                            <where>c.name = ?</where> (3)
                        </jpql>
                    </condition>
                </jpqlFilter>
            </configuration>
        </configurations>
    </genericFilter>
</layout>
1 genericFilter 组件的绑定了数据加载器。
2 可选的 join 子句。
3 必需的 where 子句。? 表示需要由用户输入的参数。

编程式配置

另一种定义的方式是在视图控制器中编程式配置:

@Autowired
private UiComponents uiComponents;

@Autowired
private SingleFilterSupport singleFilterSupport;

@ViewComponent
private GenericFilter jfdtcGenericFilter;

@Autowired
private JpqlFilterSupport jpqlFilterSupport;

@Subscribe
public void onInit(final InitEvent event) {
    DesignTimeConfiguration javaDefaultConfigurationJF =
            jfdtcGenericFilter.addConfiguration("javaDefaultConfiguration", "JpqlFilter configuration"); (1)
    DataLoader dataLoaderJF = jfdtcGenericFilter.getDataLoader();

    JpqlFilter<String> jpqlFilter =
            uiComponents.create(JpqlFilter.class); (2)
    jpqlFilter.setConditionModificationDelegated(true);
    jpqlFilter.setDataLoader(dataLoaderJF);
    jpqlFilter.setCondition("c.name = ?", "join {E}.city c");
    jpqlFilter.setParameterClass(String.class);
    jpqlFilter.setLabel("City name is");
    jpqlFilter.setParameterName(jpqlFilterSupport.generateParameterName(
            String.valueOf(jpqlFilter.getId()),
            jpqlFilter.getParameterClass().getSimpleName()));
    jpqlFilter.setValueComponent(singleFilterSupport.generateValueComponent(
            dataLoaderJF.getContainer().getEntityMetaClass(),
            jpqlFilter.hasInExpression(),
            jpqlFilter.getParameterClass())); (3)
    javaDefaultConfigurationJF.getRootLogicalFilterComponent()
            .add(jpqlFilter); (4)

    jfdtcGenericFilter.setCurrentConfiguration(javaDefaultConfigurationJF); (5)
}

无参数过滤器

jpqlFilter 还支持创建无参数条件,用户只能选择是否使用该条件。

例如,直接在 where 子句中设置城市的名称。用户只能选择显示该城市的客户:

generic filter jpql filter no parameter
<layout>
    <genericFilter id="noParameterFilter"
            dataLoader="customerDl">
        <properties include=".*"/>
        <configurations>
            <configuration id="jpqlConfigurationNoParams"
                           name="JpqlFilter No parameters">
                <jpqlFilter label="Show customers from London"
                            parameterClass="java.lang.Void"
                            defaultValue="true"> (1)
                    <condition>
                        <jpql>
                            <join>join {E}.city c</join>
                            <where>c.name = 'London'</where> (2)
                        </jpql>
                    </condition>
                </jpqlFilter>
            </configuration>
        </configurations>
    </genericFilter>
</layout>
1 parameterClass="java.lang.Void" 表示过滤器无参数,defaultValue=true 表示会使用该条件。
2 城市名固定为 'London' 且无法在运行时修改。

另一种定义的方式是在视图控制器中编程式配置:

@Autowired
private UiComponents uiComponents;

@Autowired
private SingleFilterSupport singleFilterSupport;

@ViewComponent
private GenericFilter jfdtcGenericFilterNoParameter;

@Autowired
private JpqlFilterSupport jpqlFilterSupport;

@Subscribe
public void onInit(final InitEvent event) {
    DesignTimeConfiguration javaConfiguration = jfdtcGenericFilterNoParameter
            .addConfiguration("javaConfiguration", "No-parameter JpqlFilter configuration");
    DataLoader dataLoaderNoParam = jfdtcGenericFilterNoParameter.getDataLoader();

    JpqlFilter<Boolean> jpqlFilterNoParameter = uiComponents.create(JpqlFilter.class);
    jpqlFilterNoParameter.setConditionModificationDelegated(true);
    jpqlFilterNoParameter.setDataLoader(dataLoaderNoParam);
    jpqlFilterNoParameter.setCondition("c.name = 'London'", "join {E}.city c");
    jpqlFilterNoParameter.setParameterClass(Void.class);
    jpqlFilterNoParameter.setLabel("Show customers from London");
    jpqlFilterNoParameter.setParameterName(jpqlFilterSupport
            .generateParameterName(
                    String.valueOf(jpqlFilterNoParameter.getId()),
                    jpqlFilterNoParameter.getParameterClass().getSimpleName()));
    jpqlFilterNoParameter.setValueComponent(singleFilterSupport
            .generateValueComponent(dataLoaderNoParam.getContainer().getEntityMetaClass(),
                    jpqlFilterNoParameter.hasInExpression(),
                    jpqlFilterNoParameter.getParameterClass()));

    jpqlFilterNoParameter.setValue(true);
    javaConfiguration.setFilterComponentDefaultValue(
            jpqlFilterNoParameter.getParameterName(),
            jpqlFilterNoParameter.getValue());

    jfdtcGenericFilterNoParameter.setCurrentConfiguration(javaConfiguration);

    javaConfiguration.getRootLogicalFilterComponent()
            .add(jpqlFilterNoParameter);
}

groupFilter

groupFilter - 组合条件过滤器 是将多个条件绑定为一组。组内的条件可以使用逻辑运算符(ANDOR)连接。本节的声明式和编程式配置都可以在视图中创建如下过滤器:

generic filter group filter

声明式配置

genericFilter 的配置可以在视图的 XML 文件中声明式指定。以下示例展示如何配置 groupFilter,组合了两个 propertyFilter

<genericFilter id="genericFilterGroup"
        dataLoader="customerDl">
    <properties include=".*"/>
    <configurations>
        <configuration id="groupFilter"
                       name="groupFilter"
                       default="true">
            <groupFilter operation="OR"> (1)
                <propertyFilter property="rewardPoints"
                                operation="GREATER_OR_EQUAL"
                                operationEditable="true"/>
                <propertyFilter property="hobby"
                                operation="EQUAL"
                                operationEditable="true"/>
            </groupFilter>
        </configuration>
    </configurations>
</genericFilter>

编程式配置

另一种定义的方式是在视图控制器中编程式配置:

@Autowired
private UiComponents uiComponents;

@Autowired
private SingleFilterSupport singleFilterSupport;

@ViewComponent
private GenericFilter gfdtcGenericFilter;

@Subscribe
public void onInit(final InitEvent event) {
    DesignTimeConfiguration javaDefaultConfigurationGF =
            gfdtcGenericFilter.addConfiguration("javaDefaultConfiguration",
                    "GroupFilter configuration"); (1)
    DataLoader dataLoaderGF = gfdtcGenericFilter.getDataLoader();

    GroupFilter groupFilter =
            uiComponents.create(GroupFilter.class); (2)
    groupFilter.setConditionModificationDelegated(true);
    groupFilter.setDataLoader(dataLoaderGF);
    groupFilter.setOperation(LogicalFilterComponent.Operation.OR); (3)

    PropertyFilter<Integer> rewardsPropertyFilter =
            uiComponents.create(PropertyFilter.class);
    rewardsPropertyFilter.setConditionModificationDelegated(true);
    rewardsPropertyFilter.setDataLoader(dataLoaderGF);
    rewardsPropertyFilter.setProperty("rewardPoints");
    rewardsPropertyFilter.setOperation(PropertyFilter.Operation.GREATER_OR_EQUAL);
    rewardsPropertyFilter.setOperationEditable(true);
    rewardsPropertyFilter.setParameterName(PropertyConditionUtils
            .generateParameterName(rewardsPropertyFilter.getProperty()));
    rewardsPropertyFilter.setValueComponent(singleFilterSupport.generateValueComponent(
            dataLoaderGF.getContainer().getEntityMetaClass(),
            rewardsPropertyFilter.getProperty(),
            rewardsPropertyFilter.getOperation()));

    groupFilter.add(rewardsPropertyFilter); (4)

    PropertyFilter<String> hobbyPropertyFilter =
            uiComponents.create(PropertyFilter.class);
    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); (5)
    javaDefaultConfigurationGF.getRootLogicalFilterComponent()
            .add(groupFilter); (6)
}
1 添加一个设计时配置,方法接收两个参数:配置id和配置名。
2 创建 GroupFilter 组件,并设置其属性。
3 设置 OR 运算符。
4 添加 PropertyFilter 作为第一个条件,按照奖励点数对用户进行过滤。
5 添加 PropertyFilter 作为第二个条件,按照爱好对用户进行过滤。
6 将创建的组过滤器添加至配置。

注册过滤器组件

如需在框架内创建并注册 UI 过滤器组件,需要以下对象:

  • 一个组件类 - UI 组件,展示在 genericFilter 内部。

  • 一个模型类 - 保存过滤器组件的非持久化状态。模型类用来保存过滤器组件状态至数据库并在运行时展示该状态。模型类需要继承 FilterCondition 类。参考 PropertyFilterCondition 类作为示例。

  • 一个转换器类 - 在组件和模型之间转换。转换器类需实现 FilterConverter 接口。

  • 一个模型的详情界面。其标识符可以通过 withDetailViewId 方法指定。如果未指定标识符,则标识符默认为 JmixEnity 获取的模型名称加上 ViewRegistry.DETAIL_VIEW_SUFFIX 后缀。

PropertyFilter 注册示例:

@Bean("flowui_PropertyFilterRegistration")
public FilterComponentRegistration registerPropertyFilter() {
    return FilterComponentRegistrationBuilder.create(PropertyFilter.class,
                    PropertyFilterCondition.class,
                    PropertyFilterConverter.class)
            .build();
}

所有注册的过滤器组件都在 Add condition 对话框的 Create 中显示。

可以替换 Jmix 框架中注册的过滤器组件为自定义的组件,只需在 FilterComponentRegistration bean 使用 @Order 注解提高自定义组件的优先级。

XML 属性

使用 Jmix UI inspector 查看和编辑组件的属性。

propertyFilter 属性

jpqlFilter 属性

defaultValue

设置默认值。

hasInExpression

是否可以使用集合值,以及 IN 子句。

labelVisible

设置 label 的可见性。

parameterClass

指定参数的类型。例如 java.lang.String

groupFilter 属性

operation

设置组内条件连接的逻辑运算符。支持 ANDOR

operationTextVisible

是否显示运算符的名称。

summaryText

为该条件设置一个摘要描述。

事件和处理器

propertyFilter 的事件

jpqlFilter 的事件

validator

为组件添加一个 validator 实例。

groupFilter 的事件