 
Tutorial
Step 1: Implementing the search bar
| This step introduces the concept of a linkki PMO. You will learn how to create a so-called section with such a PMO and the annotation @UISection. Along with that, you will also be introduced to the first component annotations@UITextFieldand@UIButton. | 
The linkki archetype already provides the fundamental setup for your BusinessPartnerView. In this step, you will create an input field in the view where the user can enter a search term and trigger the search.
 
Creating the section to enter search criteria
| In linkki, each layout element is represented by a Presentation Model Object (PMO) that is annotated with a layout annotation. The most commonly used layout is the section ( @UISection). | 
To start with the first layout, create a class with the name SearchSectionPmo and annotate it with @UISection.
To implement the text field for search term input, follow the following steps:
- 
Create a new field searchTextthat stores the user’s input.
- 
Create and implement the getter method for the property searchTextwith the signatureString getSearchText().
- 
Annotate the getter method with @UITextField. The annotation requires a valuepositionwhich can set to an arbitrary positive integer value, e.g. 10.
- 
Create and implement the setter method for the property searchText. This method should have the signaturepublic void setSearchText(String).
The finished implementation looks like this:
@UISection
public class SearchSectionPmo {
    private String searchText = "";
    @UITextField(position = 10, label = "")
    public String getSearchText() {
        return searchText;
    }
    public void setSearchText(String searchText) {
        this.searchText = searchText;
    }
}| Just like layouts, input components are also represented by annotations. The built-in annotations cover the components that are most commonly used in a form. It is also possible to create your annotations for custom components. | 
The UI element UITextField is declared via the annotation @UITextField. It is followed by two properties: position and label.
| The attribute positiondefines the display order of the components inside a layout. | 
| The getter method that is annotated with UI element annotation determines what is displayed in the field. The setter method defines what happens with the user input. The mechanism of a PMO is further explained in the documentation. In summary, whenever the user input changes, the  The following image illustrates the data binding for the property    Figure 2. Data binding | 
- 
Create a new field searchConsumerof typeConsumer<String>.
- 
Create a constructor with the signature SearchSectionPmo(Consumer<String>)which assigns the argument to the fieldsearchConsumer.
- 
Create a new method searchwith the signaturepublic void search()
- 
Implement the method with searchConsumer.accept(searchText)
- 
Annotate the method with @UIButton.- 
The positionshould be higher than the position of@UITextField, e.g. 20.
- 
The captionshould be set to "Start Search".
 
- 
The finished implementation should look like this:
private Consumer<String> searchConsumer;
public SearchSectionPmo(Consumer<String> searchConsumer) {
    this.searchConsumer = searchConsumer;
}
@UIButton(position = 20, caption = "Start Search")
public void search() {
    searchConsumer.accept(getSearchText());
}| As a button do not store any values, the annotation is not added to a getter method, but a void method. Whenever the user clicks on the button, the method search()is invoked. The corresponding PMO property is calledsearch. | 
The search action itself is a functionality that should not be directly implemented in the PMO as it requires interaction with external systems. Thus it should be passed to the PMO as a constructor argument.
| In your application, you will often use the functional interfaces org.linkki.util.handler.HandlerandConsumer<T>in order to separate a button’s execution logic from its definition within the Presentation Model Object (PMO) classes. TheHandleris a representation of a method without arguments and without a return value. | 
Creating and showing SearchSectionPmo on a Page
Now that you have the search input section, follow the following steps to create and display the section represented by SearchSectionPmo:
- 
Create a Class SearchPagethat extendsAbstractPage.
- 
Create a field bindingManagerof type BindingManager and initialize it withnew DefaultBindingManager().
- 
Implement the method getBindingManager()which returns the fieldbindingManager.
- 
Define a new method public void search(String)with no implementation yet.
- 
Implement the method createContent with addSection(new SearchSectionPmo(this::search)).
The finished implementation should look like this:
public class SearchPage extends AbstractPage { (1)
    private final BindingManager bindingManager = new DefaultBindingManager();
    public SearchPage(BusinessPartnerRepository partnerRepository) {
        this.partnerRepository = partnerRepository;
    }
    @Override
    protected BindingManager getBindingManager() {
        return bindingManager;
    }
    @Override
    public void createContent() {
        addSection(new SearchSectionPmo(this::search));
    }
    public void search(String searchText) {
        // will be implemented later
    }
}| 1 | AbstractPageis an implementation ofPageby linkki in which sections can be conveniently created and added by providing the corresponding PMOs. | 
Next, implement the search functionality as follows:
- 
Create a new field foundPartnerswith the typeList<BusinessPartner>to store the search results.
- 
Initialize the field foundPartnerswithnew ArrayList<>().
- 
Extend the constructor of SearchPagewith an additional argument of typeorg.linkki.samples.appsample.model.BusinessPartnerRepository. This type is provided by the dependencytutorial-modeland implements the search functionality.
- 
Store the constructor argument in a new field partnerRepository.
- 
Implement the method search: Execute the methodfindBusinessPartnerfrompartnerRepositorywith the method argument and store the result in the fieldfoundPartners.
The finished implementation should look like this:
private final BusinessPartnerRepository partnerRepository;
private final List<BusinessPartner> foundPartners = new ArrayList<>();
public void search(String searchText) {
    var searchResults = partnerRepository.findBusinessPartners(searchText);
    foundPartners.clear();
    foundPartners.addAll(searchResults);
}Showing SearchPage in BusinessPartnerView
The SearchPage is still not displayed yet. To create and display the page, go to the class BusinessPartnerView and modify the class as followed:
- 
Extend the constructor with an argument of type BusinessPartnerRepository.
- 
Annotate the constructor with @Autowired.
- 
Create a new Headlineusing the constructor and the argument"Partner Search"and add it to the view withadd.
- 
Create a new SearchPageusing the constructor.
- 
Call the init()method of the createdSearchPageto create the content of the page and add the createdSearchPageto the view withadd.
The finished implementation should look like this:
@Autowired
public BusinessPartnerView(BusinessPartnerRepository repository) {
    Headline headline = new Headline("Partner Search");
    add(headline);
    SearchPage searchPage = new SearchPage(repository);
    searchPage.init();
    add(searchPage);
}The method AbstractPage.init() takes care of creating the page after the constructor has been called.
Viewing the result in the application
If you run your application now, you should be able to see the SearchSectionPmo. The view begins with the title "Partner Search" and is followed by a search bar and a search button called "Start Search".
 
For now, clicking the search button does not affect the UI. The next step extends the UI to display the search result.
