Filtering grids is quite slick, and fairly easy once you get the hang of it.
First, understand that the Grid
object is not actually filtered. The DataProvider
backing the Grid
is filtered. The Grid
automatically updates its own display to match changes to the data provider.
Below is an entire example app. When it first appears, we see four items it the Grid
widget. These items are simply java.time.LocalDate
objects.

When the user enters a year number in the IntegerField
, we apply a filter to the ListDataProvider
object backing our grid. If the user clears the year number from that IntegerField
, we clear all filters from our data provider.

Setting and clearing the filter(s) takes effect immediately. This point threw me, with me thinking that I must somehow “apply” the filters after calling setFilter
or addFilter
. But, no, the Grid
automatically updates its display — with no further code on my part. The predicate test defined as part of your filter is automatically applied to each item in the ListDataProvider
object’s data set. Those items that pass the test are displayed, while items that fail the test are suppressed from display.
The setting and clearing of filters is done in a value-change listener on the IntegerField
widget. When a user enters a number (and leaves the field, such as by pressing Tab or Return), our listener object automatically is called, with an event object passed. Notice that we test for a null being retrieved from the IntegerField
. A null means the user cleared the existing entry, leaving the field blank.
Where did we define our ListDataProvider
object to back our Grid
object? That data provider was instantiated automatically for us when we passed a List
to the Grid::setItems
method.
By the way, you can have a Grid
automatically display columns using the JavaBeans-style naming conventions (getter/setter methods). But here in this example we defined our columns explicitly, their values generated by calling the LocalDate ::
method references we pass.
package work.basil.example;
import com.vaadin.flow.component.AbstractField;
import com.vaadin.flow.component.dependency.CssImport;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.IntegerField;
import com.vaadin.flow.data.provider.ListDataProvider;
import com.vaadin.flow.router.Route;
import java.time.LocalDate;
import java.time.Month;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* The main view contains a button and a click listener.
*/
@Route ( "" )
//@PWA ( name = "Project Base for Vaadin", shortName = "Project Base" )
@CssImport ( "./styles/shared-styles.css" )
@CssImport ( value = "./styles/vaadin-text-field-styles.css", themeFor = "vaadin-text-field" )
public class MainView extends VerticalLayout
{
private Grid < LocalDate > grid;
private IntegerField yearField;
public MainView ( )
{
yearField = new IntegerField( "Filter years before: " );
yearField.addValueChangeListener(
( AbstractField.ComponentValueChangeEvent < IntegerField, Integer > event ) -> {
Integer year = event.getValue();
// If the user cleared the field, its value is null. In such a case, clear all filters.
// If the user entered a year number into this field, specify a filter.
if ( Objects.isNull( year ) )
{
( ( ListDataProvider < LocalDate > ) grid.getDataProvider() ).clearFilters();
} else
{
( ( ListDataProvider < LocalDate > ) grid.getDataProvider() ).setFilter( ( LocalDate localDate ) -> localDate.getYear() < year );
}
}
);
grid = new Grid <>();
List < LocalDate > dates = List.of(
LocalDate.of( 2020 , Month.JANUARY , 23 ) ,
LocalDate.of( 2019 , Month.FEBRUARY , 24 ) ,
LocalDate.of( 2022 , Month.MARCH , 25 ) ,
LocalDate.of( 2011 , Month.APRIL , 26 )
);
grid.setItems( new ArrayList < LocalDate >( dates ) );
grid.addColumn( LocalDate :: toString );
grid.addColumn( LocalDate :: getYear );
grid.addColumn( LocalDate :: getDayOfWeek );
this.add( yearField , grid );
}
}
You can install multiple filters by calling addFilter
instead of setFilter
. The predicates are effective combined as AND rather than as OR. So all the predicate tests must pass for an item to be displayed. Call clearFilters
to remove any filters. Calling setFilter
clears any existing filters and installs a single filter.