Компоненты 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, property и operation.
4 Добавляет фильтр в конфигурацию. LogicalFilterComponent является корневым элементом конфигурации.
5 Устанавливает текущую конфигурацию.

jpqlFilter

jpqlFilter позволяет выполнять фильтрацию на основе JPQL-запроса. Он изменяет JPQL-запрос загрузчика данных, добавляя необязательное предложение join и обязательное предложение where и, следовательно, уточняя результаты поиска.

И декларативная, и программная конфигурации, представленные в этом разделе, создают следующий фильтр в экране:

generic filter jpql filter

Декларативная конфигурация

Конфигурация genericFilter может быть задана декларативно, внутри XML-дескриптора экрана. Смотрите следующий пример конфигурации с 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 объединяет несколько условий в группу. Условия в группе применяются на основе логического оператора (AND или OR). И декларативная, и программная конфигурации, представленные в этом разделе, создают следующий фильтр в экране:

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. Если идентификатор не указан, то идентификатор будет равен имени модели, полученному из JmixEntity, с ViewRegistry.DETAIL_VIEW_SUFFIX.

Рассмотрим пример регистрации PropertyFilter:

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

Все зарегистрированные компоненты фильтра становятся доступными для использования в качестве элементов в меню Create диалогового окна Add condition.

Вы можете заменить компонент фильтра, зарегистрированный во фреймворке Jmix, своей собственной реализацией. Чтобы определить приоритет реализации, используйте аннотацию @Order на бине FilterComponentRegistration.

Атрибуты

Просматривайте и редактируйте атрибуты компонента, используя инспектор Jmix UI.

Атрибуты propertyFilter

Атрибуты jpqlFilter

defaultValue

Устанавливает значение по умолчанию.

hasInExpression

Определяет, может ли коллекция быть принята и помещена в предложение IN.

labelVisible

Устанавливает видимость надписи.

parameterClass

Указывает класс, представляющий желаемый тип параметра. Например: java.lang.String.

Атрибуты groupFilter

operation

Указывает логический оператор, используемый для объединения условий в группе. Возможные значения: AND, OR.

operationTextVisible

Определяет, отображается ли название операции.

summaryText

Указывает краткое описание для этого условия фильтра.

Обработчики

Обработчики propertyFilter

Обработчики jpqlFilter

validator

Добавляет экземпляр валидатора к компоненту.

Обработчики groupFilter