Ваадин: Цепочка фильтров? - PullRequest
3 голосов
/ 21 февраля 2020

У меня сейчас особая проблема - у меня есть сетка, в которой я пытаюсь фильтровать данные через несколько фильтров. Для этого я использую текстовые поля, которые служат полями ввода для моего критерия фильтрации.

Моя сетка состоит из трех столбцов (Имя, Фамилия, Адрес), и я хотел бы иметь возможность объединить операции фильтрации один за другим. Все значения взяты из базы данных MySQL.

По существу процесс фильтрации должен go выглядеть следующим образом:

FirstName ^ LastName ^ Address

Например, сетка с тремя столбцами:

enter image description here

table

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

enter image description here

table1

Однако, если я решив ввести D в фильтр «Фамилия», он возвращает следующие результаты (игнорирует изменения, внесенные первым фильтром):

enter image description here

table3

Вместо ожидаемого результата, который выглядел бы так:

enter image description here enter image description here

Способ фильтрации по сетке выглядит следующим образом:

firstNameFilter.addValueChangeListener( e->
    {
        Notification.show(e.getValue());

        ldp.setFilter(desc -> 
        {
            return StringUtils.containsIgnoreCase(desc.getFName(), firstNameFilter.getValue());
        });
    });     
    firstNameFilter.setValueChangeMode(ValueChangeMode.EAGER);

Каков наилучший способ фильтрации по нескольким столбцам с учетом предыдущих действий фильтра?

1 Ответ

8 голосов
/ 21 февраля 2020

listDataProvider.setFilter(...) перезапишет любой существующий фильтр.
Я написал ответ об этой самой топике c, с полным примером кода, готовым для копирования-вставки, и скриншотами, показывающими, что кратный фильтры работают должным образом.
Наиболее важный вывод из этого заключается в следующем:

Каждый раз, когда изменяется любое значение фильтра, я сбрасываю текущий фильтр с помощью setFilter. Но внутри этого нового фильтра я буду проверять значения ВСЕХ полей фильтра, а не только значение поля, значение которого только что изменилось. Другими словами, у меня всегда активен только один единственный фильтр, но этот фильтр учитывает все определенные значения фильтра.


Вот как это может выглядеть с вашим кодом:

firstNameFilter.addValueChangeListener( e-> this.onFilterChange());
lastNameFilter.addValueChangeListener( e-> this.onFilterChange());
addressFilter.addValueChangeListener( e-> this.onFilterChange());
// sidenote: all filter fields need ValueChangeMode.EAGER to work this way


private void onFilterChange(){
    ldp.setFilter(desc -> {
        boolean fNameMatch = true;
        boolean lNameMatch = true;
        boolean addressMatch = true;

        if(!firstNameFilter.isEmpty()){
            fNameMatch = StringUtils.containsIgnoreCase(desc.getFName(), firstNameFilter.getValue());
        }
        if(!lastNameFilter.isEmpty()){
            lNameMatch = StringUtils.containsIgnoreCase(desc.getLName(), lastNameFilter.getValue());
        }
        if(!addressFilter.isEmpty()){
            addressMatch = StringUtils.containsIgnoreCase(desc.getAddress(), addressFilter.getValue());
        }

        return fNameMatch && lNameMatch && addressMatch;
    });
});     
...