Creating a Reusable Form Component to Edit Contacts

This tutorial teaches you how to create custom elements and use them in views when building Hilla applications.

The list view now has a grid to display Contact objects. To complete the view, you need to create a form to edit contacts.

A screenshot of the application highlighting the contact editing form

This chapter covers:

  • creating a new component,

  • importing and using a custom component.

Creating a New Component

Create a new file in the same directory as the list view: frontend/views/list/contact-form.ts.

Add the following content to the file:

import { html } from 'lit';
import { customElement } from 'lit/decorators.js';
import { View } from 'Frontend/views/view';
import '@vaadin/button';
import '@vaadin/combo-box';
import '@vaadin/text-field';

export class ContactForm extends View {
  render() {
    return html`
      <vaadin-text-field label="First name"></vaadin-text-field>
      <vaadin-text-field label="Last name"></vaadin-text-field>
      <vaadin-text-field label="Email"></vaadin-text-field>
      <vaadin-combo-box label="Status"></vaadin-combo-box>
      <vaadin-combo-box label="Company"> </vaadin-combo-box>

      <div class="flex gap-s">
        <vaadin-button theme="primary">Save</vaadin-button>
        <vaadin-button theme="error">Delete</vaadin-button>
        <vaadin-button theme="tertiary">Cancel</vaadin-button>

As stated in the Introduction to Lit section, there are three main parts to defining a Lit component:

  1. Creating a class that extends from LitElement.

  2. Defining the tag name and registering the element with @customElement.

  3. Defining a template as a tagged html template literal as a return value of the render() method.

In this case, instead of directly extending LitElement, you use View. View turns off the Shadow DOM for easier application-wide theming and adds support for MobX state management, which you need later on.

The tag name in @customElement needs to include a dash (-). It’s good practice to use the same name for the file and the tag name – contact-form in this case.

The template uses three components from the Vaadin component set: text field, combo box, and button. The buttons specify different theme variants using the theme="variant" attribute.

Using a Custom Component in Another View

You need to import the new contact-form component in list-view before using it.

Add the following import at the end of the imports in list-view.ts:

import './contact-form';

Then, add the component to the template right after the </vaadin-grid> end tag.

<contact-form class="flex flex-col gap-s"></contact-form>

Here, you use the utility CSS classes again to turn the form into a flex container with spacing between components.

As a last step, make the form wider by adding the following CSS:

list-view contact-form {
  width: 25em;

The themes folder contains the CSS for the project. Be sure to scope your CSS selectors with the component name when using View as the base class. This ensures that you don’t accidentally apply styles to other components.

Open your browser at localhost:8080, and you should see the following:

An empty list view with the contact form

If your development server isn’t running, start it with the mvn command from the command line.

Now that you have the view ready, you can turn your focus to the backend and create an endpoint to fetch data from, and persist it to, the server.