JoffJoff
JoffJoff

Reputation: 145

Vaadin: Daisy chain of filters?

I have this particular problem now - I have a grid that I am trying to have the data filtered through multiple filters. For that, I am using textboxes that serve as input fields for my filtering criterion.

My grid has three columns (First Name, Last Name, Address) and I would like to be able to chain the filtering operations one after the other. All of the values are taken from a MySQL database.

Essentially the filter process should go like this:

FirstName ^ LastName ^ Address

For example, grid with three columns:

enter image description here

table

And in the filter for First Name column, I input the variables Aa, which would result in the table looking like this:

enter image description here

table1

However, if I decided input D into the Last Name filter it returns results like this (ignores the modifications by the first filter):

enter image description here

table3

Instead of the expected result which would look like this:

enter image description here enter image description here

The way I am filtering through the grid is like this:

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

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

What would be the best way to filter through multiple columns whilst taking into consideration previous filter actions?

Upvotes: 3

Views: 232

Answers (1)

kscherrer
kscherrer

Reputation: 5766

listDataProvider.setFilter(...) will overwrite any existing filter.
I have written an answer about this very topic, with a complete example code ready for copy paste, and screenshots showing that the multiple filters work as expected.
The most important takeaway from it is this:

Every time that any filter value changes, I reset the current filter using setFilter. But within that new Filter, I will check the values of ALL filter fields, and not only the value of the field whose value just changed. In other words, I always have only one single filter active, but that filter accounts for all defined filter-values.


Here is how it could look with your code:

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

Upvotes: 8

Related Questions