Skip to content
Version:

Install

Maven

xml
<dependency>
    <groupId>de.mate_ds</groupId>
    <artifactId>mate-filter-panel-flow</artifactId>
</dependency>

Import

java
import de.mate_ds.flow.component.filterpanel.FilterPanel;
import de.mate_ds.flow.component.filterpanel.FilterPanelDialogBuilders.FilterPanelReorderDialogBuilder;
import de.mate_ds.flow.component.filterpanel.FilterPanelDialogBuilders.FilterPanelVisibilityDialogBuilder;
import de.mate_ds.flow.component.filterpanel.FilterPanelDialogBuilders.ItemVisibilityProvider;

Variants

Micro

Basic filter panel without header, suitable for simple search scenarios.

java
TextField username = new TextField("Username");
TextField firstName = new TextField("First name");
TextField dateOfBirth = new DatePicker("Date of birth");

FilterPanel filterPanel = new FilterPanel();
filterPanel.add(username, firstName, dateOfBirth);
filterPanel.addSearchClickEventListener(e -> { /* trigger search */ });
filterPanel.addResetClickEventListener(e -> {
    username.clear();
    firstName.clear();
    dateOfBirth.clear();
});
filterPanel.setHeaderHidden(true);

Minimal

java
TextField username = new TextField("Username");
TextField firstName = new TextField("First name");
TextField dateOfBirth = new DatePicker("Date of birth");

Span criteriaCount = new Span("0");

FilterPanel filterPanel = new FilterPanel();
filterPanel.getHeaderCollapsed().add(new Span("Active search criteria"), criteriaCount);
filterPanel.addSearchClickEventListener(e -> {
    int count = 0;
    count += username.isEmpty() ? 0 : 1:
    count += firstName.isEmpty() ? 0 : 1:
    count += dateOfBirth.isEmpty() ? 0 : 1:
    criteriaCount.setText(String.valueOf(count));

    /* trigger search */
});
filterPanel.addResetClickEventListener(e -> {
    username.clear();
    firstName.clear();
    dateOfBirth.clear();
    criteriaCount.setText("0");
});

Standard

java
 FilterPanel filterPanel = new FilterPanel();
VerticalLayout layout = new VerticalLayout(filterPanel);
layout.setSpacing(true);

Grid<User> grid = new Grid<>();
grid.setItems(users);
layout.add(grid);

Generator crit1 = new Generator("Username", true, n -> filterPanel.add(new TextField(n)));
Generator crit2 = new Generator("First name", true, n -> filterPanel.add(new TextField(n)));
Generator crit3 = new Generator("Date of Birth", true, n -> filterPanel.add(new DatePicker(n)));
List<Generator> allCriteria = List.of(crit1, crit2, crit3);

Generator col1 = new Generator("Username", n -> grid.addColumn(User::getUsername).setHeader(n));
Generator col2 = new Generator("First name", n -> grid.addColumn(User::getFirstName).setHeader(n));
Generator col3 = new Generator("Last name", n -> grid.addColumn(User::getLastName).setHeader(n));
List<Generator> allColumns = List.of(col1, col2, col3);

MenuBar views = new MenuBar();
filterPanel.getHeaderExpanded().add(new Span("Ansicht"), views);

List<View> allViews = new ArrayList<>(List.of(new View("Standard", List.of(crit1, crit2, crit3), List.of(col1, col2, col3))));

AtomicReference<View> currentView = new AtomicReference<>(allViews.get(0));

SerializableRunnable updateCriteria = () -> {
    filterPanel.getChildren().filter(c -> c instanceof HasValue).forEach(filterPanel::remove);
    currentView.get().getCriteria().forEach(Generator::generate);
};
SerializableRunnable updateColumns = () -> {
    grid.removeAllColumns();
    currentView.get().getColumns().forEach(Generator::generate);
};

MenuItem viewsItem = views.addItem("");
AtomicReference<SerializableRunnable> onViewsUpdated = new AtomicReference<>();
onViewsUpdated.set(() -> {
    viewsItem.setText(currentView.get().getName() + (currentView.get().isDirty() ? " (bearbeitet)" : ""));
    SubMenu viewsMenu = viewsItem.getSubMenu();
    allViews.forEach(v -> {
        MenuItem item = viewsMenu.addItem(v.getName() + (v.isDirty() ? " (bearbeitet)" : ""), e -> {
            currentView.set(v);
            updateCriteria.run();
            updateColumns.run();
            onViewsUpdated.get().run();
        });
        item.setCheckable(true);
        if (v.equals(currentView.get())) {
            item.setChecked(true);
        }
    });
    viewsMenu.addItem(new Hr());
    viewsMenu.addItem("Speichern", e -> {
        currentView.get().setDirty(false);
        onViewsUpdated.get().run();
    });
    viewsMenu.addItem("Speichern unter", e -> {
        FilterPanelSaveAs data = new FilterPanelSaveAs();
        data.setName(currentView.get().getName() + " (Kopie)");
        new FilterPanelSaveAsDialogBuilder(data, saved -> {
            if (allViews.stream().anyMatch(v -> v.getName().equals(saved.getName()))) {
                View newView = currentView.get().clone(saved.getName());
                allViews.add(newView);

                currentView.set(newView);
                onViewsUpdated.get().run();
                return true;
            }
            return false;
        }).build();
    });
});

updateCriteria.run();
updateColumns.run();
onViewsUpdated.get().run();

filterPanel.addSearchClickEventListener(e -> Notification.show("Search clicked"));
filterPanel.addResetClickEventListener(e -> {
Notification.show("Reset clicked");
    filterPanel.getChildren().filter(c -> c instanceof HasValue).map(c -> (HasValue) c).forEach(HasValue::clear);
});

MenuBar configuration = new MenuBar();
SubMenu anpassen = configuration.addItem("Anpassen").getSubMenu();
anpassen.addItem("Suchkriterien ein- und ausblenden", e -> {
    FilterPanelVisibilityDialogBuilder.ofCriteria(allCriteria, c -> c, c -> {
        currentView.get().setCriteria(c.stream().map(item -> {
            item.getItem().setVisibility(item.getVisibility());
            return item.getItem();
        }));
        updateCriteria.run();
        return true;
    }).build().open();
});
anpassen.addItem("Suchkriterien Reihenfolge ändern", e -> {
FilterPanelReorderDialogBuilder.ofCriteria(currentView.get().getCriteria(), Generator::getName, c -> {
currentView.get().setCriteria(c);

updateCriteria.run();
return true;
}).build().open();
});
anpassen.addItem("Tabellenspalten ein- und ausblenden", e -> {
FilterPanelVisibilityDialogBuilder.ofColumns(allColumns, c -> c, c -> {
currentView.get().setColumns(c.stream().map(item -> {
item.getItem().setVisibility(item.getVisibility());
return item.getItem();
}));

updateColumns.run();
return true;
}).build().open();
});
anpassen.addItem("Tabellenspalten Reihenfolge ändern", e -> {
FilterPanelReorderDialogBuilder.ofColumns(currentView.get().getColumns(), Generator::getName, c -> {
currentView.get().setColumns(c);

updateColumns.run();
return true;
}).build().open();
});
filterPanel.getAction().add(configuration);

Context

User

java
 public static class User {

    private String username;
    private String firstName;
    private String lastName;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((username == null) ? 0 : username.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        User other = (User) obj;
        if (username == null) {
            if (other.username != null)
                return false;
        }
        else if (!username.equals(other.username))
            return false;
        return true;
    }
}

Generator

java
private static class Generator implements ItemVisibilityProvider {

    private final String  name;
    private final boolean counter;
    private int           visibility = 1;

    private final SerializableConsumer<String> consumer;

    public Generator(String name, SerializableConsumer<String> consumer) {
        this(name, false, consumer);
    }

    public Generator(String name, boolean counter, SerializableConsumer<String> consumer) {
        this.name = name;
        this.counter = counter;
        this.consumer = consumer;
    }

    public void generate() {
        IntStream.range(0, visibility).forEach(i -> consumer.accept(name));
    }

    public String getName() {
        return name;
    }

    @Override
    public String getLabel() {
        return name;
    }

    public void setVisibility(int visibility) {
        this.visibility = visibility;
    }

    @Override
    public boolean isCounter() {
        return counter;
    }

    @Override
    public int getVisibility() {
        return visibility;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Generator other = (Generator) obj;
        if (name == null) {
            if (other.name != null)
                return false;
        }
        else if (!name.equals(other.name))
            return false;
        return true;
    }

}