Suche

Bei der Suche auf einer eigenen Seite ist es erwünscht, dass die Suchparameter direkt in der URL wieder gespiegelt werden, damit die Suche auch direkt von einer anderen Seite erreichbar ist.

Der RoutingSearchController bietet hierfür Funktionalitäten, die die Implementierung erleichtern.

SearchView

Da die Suchseite direkt per URL erreichbar sein muss, ist eine @Route-Annotation notwendig. Außerdem muss das Interface BeforeEnterObserver oder AfterNavigationObserver implementiert werden, um die URL-Parameter zu verarbeiten.

@Route(value = ContextFreeSearchView.NAME, layout = SampleApplicationLayout.class)
public class ContextFreeSearchView extends VerticalLayout implements AfterNavigationObserver {
Laut Dokumentation zum Vaadin Navigation Lifecycle wird die Initialisierung der UI eher im After-Navigation-Event vorgenommen. In diesem Event kann allerdings keine Umleitung auf eine andere Seite erfolgen. Soll bei genau einem Suchtreffer anstatt der Suchseite direkt das gefundene Objekt geöffnet werden, bietet sich das Before-Enter-Event an.

Als Seiteninhalt muss ein SearchLayoutPmo verwendet werden, welches über den SearchLayoutBuilder erstellt wird. Die Erstellung vom SearchLayoutPmo ist unabhängig von der Art der Suche, und kann im entsprechenden Abschnitt "Erstellen der Suchkomponente" nachgelesen werden.

    private final BindingContext bindingContext = new BindingContext();

    public ContextFreeSearchView() {
        add(VaadinUiCreator.createComponent(createSearchLayoutPmo(), bindingContext));
        setSizeFull();
    }

In initialize muss die Location an den RoutingSearchController weitergegeben werden. Dieser liest die Suchparameter aus der URL und führt ggfs. die Suche aus. Um die gesetzten Parameter anzuzeigen, muss der BindingContext, in dem das SearchLayoutPmo liegt, aktualisiert werden.

    @Override
    public void afterNavigation(AfterNavigationEvent event) {
        searchController.initialize(event.getLocation());
        bindingContext.modelChanged();
    }

Dem verwendeten RoutingSearchController muss der Wert der @Route-Annotation mitgegeben werden.

        return new RoutingSearchController<>(ContextFreeSearchView.NAME,
                searchService::search,
                new SampleSearchParametersMapper(),
                SampleSearchResult::getMessages);

Query Parameter Mapping

Für den Suchparametertyp muss eine Implementierung von SearchParameterMapper erstellt werden.

public class SampleSearchParametersMapper implements SearchParameterMapper<SampleSearchParameters> {

Darin befindet sich eine Methode zum Erzeugen eines Suchparameterobjektes aus Query Parametern:

    public SampleSearchParameters toSearchParameters(Map<String, List<String>> queryParams) {
        var searchParams = new SampleSearchParameters();
        var parameters = ParamsUtil.flatten(queryParams);

        searchParams.setPartnerNumber(parameters.get(PROPERTY_PARTNER_NUMBER));
        ...

Sowie eine Methode zum Erzeugen von Query Parametern aus einem Suchparameterobjekt:

    public Map<String, List<String>> toQueryParameters(SampleSearchParameters searchParams) {
        var queryParams = new LinkedHashMap<String, String>();

        queryParams.put(PROPERTY_PARTNER_NUMBER, searchParams.getPartnerNumber());
        ...

Falls jeder Parameter nur einen Wert hat, kann über ParamsUtil.flatten und ParamsUtil.flatten eine Map<String, String> statt einer Map<String, List<String>> verwendet werden. ParamsUtil bietet ebenfalls ein paar format und parse Methoden.

        queryParams.put(PROPERTY_DATE_OF_BIRTH, ParamsUtil.formatIsoDate(searchParams.getDateOfBirth()));

        ParamsUtil.parseIsoDate(parameters.get(PROPERTY_DATE_OF_BIRTH))
                .ifPresent(searchParams::setDateOfBirth);