
Step 2: Displaying the search result in a table
To display the search results, matching business partners should be shown in a table below the search bar. The user should only be able to gather brief information about the business partner for now.

SearchResultTablePmo
To build a table in linkki you need two PMO classes. The first one is a row PMO, i.e. it defines the structure of one row of the table. We call it SearchResultRowPmo
. The second one is a ContainerPmo
, it builds the table out of the rows. We call it SearchResultsTablePmo
. To get a better understanding about tables in linkki have a look at the Tables section in the UI Components chapter of the linkki Documentation.
Every row consists of a text field, a text area, and a button. The text field shall display the name of a business partner and the text area the first address of their address list. The button leads us to the PartnerDetailView
, which we are going to implement in Step 3.
Again, we do not implement the method being triggered by the button in the SearchResultRowPmo
. The difference between this case and the one in the SearchSectionPmo
is that this time we use a Consumer<T>
instead of a Handler
. That is because we have to pass the business partner whose details we want as an argument to our method.
If you want, you can also configure the width of the columns in your table. This can be done by using the annotation @UITableColumns
above the UI elements.
private BusinessPartner partner;
private Consumer<BusinessPartner> consumer;
private String firstAddress;
public SearchResultRowPmo(
BusinessPartner partner, Consumer<BusinessPartner> consumer) {
this.partner = partner;
this.consumer = consumer;
this.firstAddress = partner.getFirstAddress();
}
@ModelObject
public BusinessPartner getPartner() {
return partner;
}
@UITableColumn(expandRatio = 2)
@UIButton(position = 30, caption = "Show Details", showIcon = true,
icon = VaadinIcons.PLUS)
public void detailsButton() {
consumer.accept(partner);
}
The SearchResultsTablePmo
receives the annotation @UISection
with the caption "Search Results" and has to extend the abstract class SimpleTablePmo
which takes our model object BusinessPartner
and the SearchResultRowPmo
as type arguments. We implement the required methods by creating the constructor and a new object of SearchResultRowPmo
in the createRow
method.
@UISection(caption = "Search Results")
public class SearchResultsTablePmo
extends SimpleTablePmo<BusinessPartner, SearchResultRowPmo> {
private Consumer<BusinessPartner> consumer;
public SearchResultsTablePmo(
Supplier<List<? extends BusinessPartner>> modelObjectsSupplier,
Consumer<BusinessPartner> showDetailsConsumer) {
super(modelObjectsSupplier);
this.consumer = showDetailsConsumer;
}
@Override
protected SearchResultRowPmo createRow(BusinessPartner partner) {
return new SearchResultRowPmo(partner, consumer);
}
}
Add table to SearchPage
We now complete the SearchPage
. Adding the section to the SearchPage
is done as before. The consumer for the SearchResultsTablePmo
will be defined in the constructor of the MainView
. Similar to the layout definition in the MainView
, we set the expand ratio of the SearchSectionPmo
to 0 in order to use only the required space for it. The expand ratio of the SearchResultsTablePmo
is set to 1, to fill the remaining space. To make sure that the SearchResultsTablePmo
receives the rest of the page and does not cross its borders, we set it to full size.
@Override
public void createContent() {
AbstractSection searchSection =
addSection(new SearchSectionPmo(this::search));
setExpandRatio(searchSection, 0);
SearchResultsTablePmo searchResultsTablePmo =
new SearchResultsTablePmo(
() -> displayedPartners, showDetailsConsumer);
AbstractSection resultSection = addSection(searchResultsTablePmo);
setSizeFull();
setExpandRatio(resultSection, 1);
resultSection.setSizeFull();
}
Now we switch to the MainView
and define the consumer.
public MainView(BusinessPartnerRepository repository) {
...
Consumer<BusinessPartner> showDetailsConsumer =
this::showPartnerDetails;
SearchPage searchPage =
new SearchPage(repository, showDetailsConsumer);
...
}
public void showPartnerDetails(BusinessPartner partner) {
}
We implement the method showPartnerDetails
and leave it empty for now. This method will be responsible for the navigation to the PartnerDetailView
that will be implemented in the next step.
If we start the application now, we can search for an arbitrary string and see all the matching business partners in the result table below the search bar. For example searching for "doe" shows us almost all the results that our repository contains.