我将提交使用过滤网格的方法ListDataProvider
。我的方法的目标是能够为您想要的任何列添加过滤字段, 然后过滤器可以相互组合,还有那个每个过滤器值可以随时更改为其他值。通过我的解决方案,您还可以使用 TextField 之外的其他输入字段。因此也可以使用 ComboBox 进行枚举等。
关键是当你使用setFilter
ListDataProvider 的方法,任何其他过滤器都会被忽略,因此多个过滤器不会同时工作。但是当你使用addFilter
唯一的是,您永远无法更改您定义的过滤器,只能在其上添加另一个过滤器。您可以让用户使用专用于此目的的按钮清除所有过滤器,但我想避免这种情况。
这就是我避免这个难题的方法:
每次那个any过滤器值发生变化,我使用重置当前过滤器setFilter
。但在该新过滤器中,我将检查所有过滤器字段的值,而不仅仅是值刚刚更改的字段的值。换句话说,我始终只有一个过滤器处于活动状态,但该过滤器考虑了所有定义的过滤器值。
这是带有网格的视图的完整工作代码(见下图),使用与OP原始答案相同的示例。您可以同时按字符串表示形式、年、月或星期几过滤此网格。
@Route(value = "Test", layout = MainView.class)
public class TestView extends VerticalLayout {
private Grid<LocalDate> grid;
private TextField toStringFilter, yearFilter;
private ComboBox<Month> monthFilter;
private ComboBox<DayOfWeek> dayOfWeekFilter;
public TestView() {
grid = new Grid<>(LocalDate.class, false);
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 ) ,
LocalDate.of( 2022 , Month.APRIL , 23 )
);
grid.setItems( new ArrayList< LocalDate >( dates ) );
grid.addColumn( LocalDate :: toString ).setHeader("String Representation").setKey("tostring");
grid.addColumn( LocalDate :: getYear ).setHeader("Year").setKey("year");
grid.addColumn( LocalDate :: getMonth ).setHeader("Month").setKey("month");
grid.addColumn( LocalDate :: getDayOfWeek ).setHeader("Day Of Week").setKey("dayofweek");
prepareFilterFields();
add(grid);
}
private void prepareFilterFields() {
HeaderRow headerRow = grid.appendHeaderRow();
toStringFilter = gridTextFieldFilter("tostring", headerRow);
yearFilter = gridTextFieldFilter("year", headerRow);
monthFilter = gridComboBoxFilter("month", headerRow, Month::toString, Month.values());
dayOfWeekFilter = gridComboBoxFilter("dayofweek", headerRow, DayOfWeek::toString, DayOfWeek.values());
}
private <T> ComboBox<T> gridComboBoxFilter(String columnKey, HeaderRow headerRow, ItemLabelGenerator<T> itemLabelGenerator, T... items) {
ComboBox<T> filter = new ComboBox<>();
filter.addValueChangeListener(event -> this.onFilterChange());
filter.setItemLabelGenerator(itemLabelGenerator);
filter.setItems(items);
filter.setWidthFull();
filter.setClearButtonVisible(true);
headerRow.getCell(grid.getColumnByKey(columnKey)).setComponent(filter);
return filter;
}
private TextField gridTextFieldFilter(String columnKey, HeaderRow headerRow) {
TextField filter = new TextField();
filter.setValueChangeMode(ValueChangeMode.TIMEOUT);
filter.addValueChangeListener(event -> this.onFilterChange());
filter.setWidthFull();
headerRow.getCell(grid.getColumnByKey(columnKey)).setComponent(filter);
return filter;
}
private void onFilterChange(){
ListDataProvider<LocalDate> listDataProvider = (ListDataProvider<LocalDate>) grid.getDataProvider();
// Since this will be the only active filter, it needs to account for all values of my filter fields
listDataProvider.setFilter(item -> {
boolean toStringFilterMatch = true;
boolean yearFilterMatch = true;
boolean monthFilterMatch = true;
boolean dayOfWeekFilterMatch = true;
if(!toStringFilter.isEmpty()){
toStringFilterMatch = item.toString().contains(toStringFilter.getValue());
}
if(!yearFilter.isEmpty()){
yearFilterMatch = String.valueOf(item.getYear()).contains(yearFilter.getValue());
}
if(!monthFilter.isEmpty()){
monthFilterMatch = item.getMonth().equals(monthFilter.getValue());
}
if(!dayOfWeekFilter.isEmpty()){
dayOfWeekFilterMatch = item.getDayOfWeek().equals(dayOfWeekFilter.getValue());
}
return toStringFilterMatch && yearFilterMatch && monthFilterMatch && dayOfWeekFilterMatch;
});
}
}
Unfiltered Grid:
Filtered By Year:
Filtered By Year AND Month: