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:
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:
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:
<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:
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 thePropertyFilterCondition
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 theJmixEntity
, withViewRegistry.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. |
jpqlFilter attributes
id - classNames - colspan - defaultValue - enabled - errorMessage - hasInExpression - helperText - invalid - label - labelVisible - parameterClass - readOnly - required - requiredIndicatorVisible - requiredMessage - tabIndex - themeNames - visible - width
groupFilter attributes
id - classNames - colspan - enabled - operation - operationTextVisible - summaryText - visible
Handlers
jpqlFilter handlers
validator
Adds a validator instance to the component.