> Markdown version of [Connecting Contact Form to Java](https://vaadin.com/docs/v14/tools/designer/getting-started/designer-connecting-your-contact-form-to-java). Section index: [llms.txt](https://vaadin.com/docs/v14/tools/llms.txt)

## <a id="java-contact-form"></a>Connecting Contact Form to Java

Now that the work with the grid is complete, we still need to configure the contact form, and bind it to the values displayed in the grid.

## <a id="java-configure-contact-form"></a>Configure the Contact Form

To make it possible to bind the fields of a contact bean to the form, the form’s fields must be present as members in the `ContactForm` class. We can add the fields to the class using Designer, but need to be careful with naming them because Vaadin binder works by matching the bean and field names. The `Contact` bean has fields named: `firstName`, `lastName`, `email`, `company`, and `status`. When we connect the fields from `contact-form`, we need to use these exact names.

1. In Designer, open `contact-form`.

2. Select the first name field, give it the "firstName" id attribute, and then connect it by clicking the Java icon in the outline. This connects the first name field with the "firstName" id.

3. Repeat the procedure from step 2 above for the other fields and buttons in the form:

   1. Last name field = "lastName" id attribute.

   2. Email field = "email" id attribute.

   3. Company field = "company" id attribute.

   4. Status field = "status" id attribute.

   5. Save button = "save" id attribute.

   6. Delete button = "delete" id attribute.

   7. Close button = "close" id attribute.

[Image: Connect the form fields in Designer.]

After this is done in Designer, you should have the following fields in the `ContactForm` class:

`ContactForm.java`

```java
    @Id("firstName")
    private TextField firstName;
    @Id("lastName")
    private TextField lastName;
    @Id("email")
    private EmailField email;
    @Id("company")
    private ComboBox<String> company;
    @Id("status")
    private ComboBox<String> status;
    @Id("save")
    private Button save;
    @Id("delete")
    private Button delete;
    @Id("close")
    private Button close;
```

Two things must still be added in the `ContactForm` class. First, the items in the combo boxes are still not set. We can get the list of companies and statuses from the `ContactRepository`, and set the combo boxes using those lists. Second, we need to add getters for the save, delete, and close buttons so that we can use those from inside the `MainView` class in order to listen to events inside the form.

Here’s the full `ContactForm` class that implements the above changes:

`ContactForm.java`

```java
@Tag("contact-form")
@JsModule("./src/views/contact-form.ts")
public class ContactForm extends LitTemplate {

    @Id("firstName")
    private TextField firstName;
    @Id("lastName")
    private TextField lastName;
    @Id("email")
    private EmailField email;
    @Id("company")
    private ComboBox<String> company;
    @Id("status")
    private ComboBox<String> status;
    @Id("save")
    private Button save;
    @Id("delete")
    private Button delete;
    @Id("close")
    private Button close;

    public ContactForm(ContactRepository contactRepository) { // (1)
        company.setItems(contactRepository.findDistinctCompanies()); // (2)
        status.setItems(contactRepository.findDistinctStatuses()); // (3)
    }

    public Button getSave() { // (4)
        return save;
    }

    public Button getDelete() {
        return delete;
    }

    public Button getClose() {
        return close;
    }
}
```

1. Adds `ContactRepository` as a parameter. The Spring framework will inject it here.

2. Sets the `company` combo box items by fetching them from `ContactRepository`.

3. Sets the `status` combo box items by fetching them from `ContactRepository`.

4. Add getters for the save, delete, and close buttons.

## <a id="connect-grid-and-form"></a>Connect Grid and Form

Now we need to ensure that when a contact is selected in the grid, the form is populated with the details from this contact. We also need to ensure that any modifications made to the contact object inside the form are persisted in the backend and that the grid is updated accordingly.

To do this, we change the `MainView` class one last time, so that it looks as follows:

`MainView.java`

```java
@Tag("main-view")
@JsModule("./src/views/main-view.ts")
@Route("")
public class MainView extends LitTemplate {

    @Id("filterText")
    private TextField filterText;
    @Id("addContactButton")
    private Button addContactButton;
    @Id("grid")
    private Grid<Contact> grid;
    @Id("contactForm")
    private ContactForm contactForm;

    private ContactRepository contactRepository;

    private Contact currentContact; // (1)

    private BeanValidationBinder<Contact> binder; // (2)

    public MainView(ContactRepository contactRepository) {
        this.contactRepository = contactRepository;

        grid.addColumn(Contact::getFirstName).setHeader("First name");
        grid.addColumn(Contact::getLastName).setHeader("Last name");
        grid.addColumn(Contact::getEmail).setHeader("Email");
        grid.addColumn(Contact::getCompany).setHeader("Company");
        grid.addColumn(Contact::getStatus).setHeader("Status");
        grid.getColumns().forEach(col -> col.setAutoWidth(true));
        updateList();

        filterText.setValueChangeMode(ValueChangeMode.LAZY);
        filterText.addValueChangeListener(e -> updateList());

        configureBinding(); // (3)
    }

    public void updateList() {
        String filterValue = filterText.getValue();
        if (filterValue == null || filterValue.isBlank()) {
            grid.setItems(contactRepository.findAll());
        } else {
            grid.setItems(contactRepository.findByFirstNameOrLastNameContainsIgnoreCase(filterValue, filterValue));
        }
    }

    private void configureBinding() {
        grid.asSingleSelect().addValueChangeListener(event -> {  // (4)
            Contact contact = event.getValue();
            if (contact != null) {
                populateForm(contact);
            } else {
                clearForm();
            }
        });

        binder = new BeanValidationBinder<>(Contact.class); // (5)
        binder.bindInstanceFields(contactForm); // (6)

        contactForm.getDelete().addClickListener(e -> { // (7)
            if (this.currentContact != null) {
                contactRepository.delete(this.currentContact); // (8)
                updateList();
                clearForm();
                Notification.show("Contact deleted.");
            }
        });

        contactForm.getClose().addClickListener(e -> { // (9)
            clearForm();
        });

        contactForm.getSave().addClickListener(e -> { // (10)
            try {
                if (this.currentContact == null) {
                    this.currentContact = new Contact();
                }
                binder.writeBean(this.currentContact); // (11)
                contactRepository.save(this.currentContact); // (12)
                updateList();
                clearForm();
                Notification.show("Contact details stored.");
            } catch (ValidationException validationException) {
                Notification.show("Please enter a valid contact details."); // (13)
            }
        });
    }

    void clearForm() {  // (14)
        populateForm(null);
    }

    void populateForm(Contact contact) {  // (15)
        this.currentContact = contact;
        binder.readBean(this.currentContact);
    }
}
```

1. An object to hold the currently selected contact.

2. A Vaadin `Binder` that uses reflection based on the provided `Contact` type to resolve bean properties. The Binder automatically adds `BeanValidator` which validates beans using JSR-303 specification.

3. Initiate binding configuration.

4. When a row is selected or deselected, populate or clear the form.

5. Instantiate the binder.

6. Bind the member fields found in the `ContactForm` object. This process is done automatically because the `ContactForm` object has member fields that are named identically to the fields found in the `Contact` bean.

7. Add a click listener to the delete button of the contact form in which the delete operations are performed.

8. Delete the currently selected contact from the backend, and refresh the grid afterwards.

9. Add a click listener to the close button of the form in which the form is simply cleared without making any modifications to the contact object.

10. Add a click listener to the save button of the contact form in which the save operations are performed.

11. Writes changes from the bound form fields to the `currentContact` object if all validators pass. If any field binding validator fails, no values are written and a `ValidationException` is thrown.

12. Save the `currentContact` object to the backend, after which update the grid and clear the form.

13. Show a notification a `ValidationException` is thrown. This can occur, for example, if an attempt is made to save a contact with a blank email field.

14. Clears the form

15. Populates the form with the provided contact.

That’s all. Now if we rerun the application, we will be able to see the form populated with the contact that was selected from the grid. Changes made to the form are now also updated in the backend and reflected in the grid.

Proceed to the last chapter and complete the tutorial: [Wrap up](https://vaadin.com/docs/v14/tools/designer/getting-started/designer-wrap-up.md).

`597896E6-2131-4CC0-9609-79FE3C406133`
