genericFilter Components

You can set a genericFilter configuration at both runtime and design time. This article provides examples of design-time genericFilter configurations employing each of three predefined filter components:

You can also create a custom filter component and use it as a part of genericFilter. See the Filter Component Registration section for details.

propertyFilter

propertyFilter adds a filtering condition based on a particular property of an entity.

This component can be also used independently. See the propertyFilter article for details.

Both declarative and programmatic configurations provided in this section create the following filter on the view:

generic filter components property filter

Declarative Configuration

A genericFilter configuration can be specified declaratively, inside the XML view descriptor. See the following example for configuration with 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 Declaration of genericFilter component bound to the data loader.
2 propertyFilter specifying a condition based on age property.

Programmatic Configuration

The other way to define the above configuration is programmatically, in the view controller:

@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 Adds a design-time configuration. The method takes two parameters: configuration id and configuration name.
2 Creates a PropertyFilter instance and set its properties.
3 Generates a component for this filter based on metaClass, property, and operation.
4 Adds the filter to configuration. LogicalFilterComponent is the root element of the configuration.
5 Sets a current configuration.

jpqlFilter

jpqlFilter enables filtering based on a JPQL query. It modifies the JPQL query of the data loader by adding an optional join and mandatory where clause and therefore refining search results.

Both declarative and programmatic configurations provided in this section create the following filter on the view:

generic filter jpql filter

Declarative Configuration

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 Declaration of genericFilter component bound to the data loader.
2 Optional join clause.
3 Mandatory where clause. ? indicates the parameter that is entered by the user.

Programmatic Configuration

The other way to define the above configuration is programmatically, in the view controller:

@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)
}

No Parameter Filter

jpqlFilter allows creating a condition that only lets the user choose whether it is applied or not. From a user standpoint it takes no parameter as it is set directly in the query.

For example, set a city name directly in the where clause. Users can then choose to show customers from this city only:

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" specifies that a condition does not expect a parameter value to be entered; defaultValue=true means that the condition is applied.
2 City name value is fixed as 'London' and cannot be changed at runtime.

This can be also be done in the view controller:

@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

The groupFilter component combines several conditions into a group. Conditions in the group are applied based on the logical operator (AND or OR). Both declarative and programmatic configurations provided in this section create the following filter on the view:

generic filter group filter

Declarative Configuration

A genericFilter configuration can be specified declaratively, inside the XML view descriptor. See the following example for configuration with groupFilter combining two propertyFilter components:

<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>

Programmatic Configuration

The other way to define the above configuration is programmatically, in the view controller:

@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 Adds a design-time configuration. The method takes two parameters: configuration id and configuration name.
2 Creates the GroupFilter component and sets its properties.
3 Sets the OR logical operation defining how conditions of the group are applied.
4 Adds PropertyFilter that filters customers by reward points as the first condition of this group.
5 Adds PropertyFilter that filters customers by their hobby as the second condition of this group.
6 Adds the created group of conditions to the configuration.

Filter Component Registration

To create and register a UI filter component in the framework, you need the following objects:

  • A component class representing a UI component that will be displayed inside the genericFilter component.

  • A model class to store non-persistent state of that component. This class will be used to save the component’s state in the database and reflect this state at runtime. Such class should extend the FilterCondition class. As an example of such class, consider the PropertyFilterCondition class in the framework.

  • A converter class for converting between a component and a model. Such class should implement the FilterConverter interface.

  • A model detail view. Its identifier can be optionally specified using the withDetailViewId method. If no identifier is specified then the identifier will be equal to the model name obtained from the JmixEntity, with ViewRegistry.DETAIL_VIEW_SUFFIX.

Consider PropertyFilter registration example:

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

All registered filter components become available for use as items in the Create menu of the Add condition dialog.

You can replace a filter component registered in the Jmix framework with your own implementation. To prioritize implementations use the @Order annotation on the FilterComponentRegistration bean.

Attributes

View and edit attributes of the component using Jmix UI inspector.

propertyFilter attributes

jpqlFilter attributes

defaultValue

Sets a default value.

hasInExpression

Determines whether a collection can be accepted and put inside the IN clause.

labelVisible

Sets the label visibility.

parameterClass

Specifies a class representing the desired parameter type. For example: java.lang.String.

groupFilter attributes

operation

Specifies a logical operator used to join conditions in a group. Possible values: AND, OR.

operationTextVisible

Determines whether the name of the operation is displayed.

summaryText

Specifies a summary for this filter condition.

Handlers

propertyFilter handlers

jpqlFilter handlers

validator

Adds a validator instance to the component.

groupFilter handlers