javavaadinvaadin-gridvaadin10

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?


Solution

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