Building a Hilla View from Components

Learn how to build reactive views using LitElement and Hilla web components.

Hilla uses the Lit library to build reactive views with declarative templates. Views are constructed using components from the Vaadin component library, HTML, and CSS. If you aren’t familiar with Lit, see Creating components.

This chapter covers:

  • Vaadin component basics

  • building reactive UIs

  • Lit basics

  • constructing a view with Vaadin components and Lit.

The Contact List View

The first view you build is the contact list view. This view lists all the contacts in the system. Users can search, add, edit, and delete contacts in this view.

You add the layout containing the header and sidebar later, in the Navigation and parent layouts chapter.

In this and the next chapter, you create the required layouts and components for the view. Then, in the chapter that follows, you create an endpoint to populate the view with data.

The list view consists of a data grid and a toolbar

For this view, you need the following Vaadin components:

Importing Vaadin Components

Before you can use Vaadin components, you need to import them. Importing the components registers the custom HTML elements with the browser. It also helps the build tool to understand what components are being used, so it can optimize the resulting JavaScript to include only the necessary components.

Add the following imports to the top of frontend/views/list/list-view.ts:

import '@vaadin/text-field';
import '@vaadin/button';
import '@vaadin/grid';
import '@vaadin/grid/vaadin-grid-column';

Defining the View Template

Now that the components are imported, you can use them in the template. The template is defined in the render() method.

Replace the contents of the render() method with the following:

render() {
  return html`
    <div class="toolbar flex gap-s">
      <vaadin-text-field placeholder="Filter by name" clear-button-visible></vaadin-text-field>
      <vaadin-button>Add Contact</vaadin-button>
    <div class="content flex gap-m h-full">
      <vaadin-grid class="grid h-full">
        <vaadin-grid-column path="firstName" auto-width> </vaadin-grid-column>
        <vaadin-grid-column path="lastName" auto-width> </vaadin-grid-column>
        <vaadin-grid-column path="email" auto-width> </vaadin-grid-column>
        <vaadin-grid-column path="" header="Status" auto-width></vaadin-grid-column>
        <vaadin-grid-column path="" header="Company" auto-width></vaadin-grid-column>
  • The text field is configured to show a placeholder text and a clear button.

  • Grid columns map to properties on an object based on the path attribute. By default, the header name is derived from the path. You can override it with header, for instance when binding to the path of a nested object.

  • The Hilla Design System comes with a set of CSS utility classes to simplify layouts and styling. Instead of having to write your own CSS for common tasks like adding margins, padding, setting sizes, and defining layouts, you can use utility CSS classes, such as flex and h-full. You can browse all the classes.

  • The layout doesn’t yet look quite as you would expect. The next step in the tutorial adds some CSS classes to fix the layout.

Adding CSS Classes to the View Component

So far, you have added CSS class names to HTML elements within the template. You also need to add classes to the <list-view> element itself. The easiest way to do this is to use the connectedCallback() lifecycle callback.

Update the connectedCallback() method in ListView as follows:

connectedCallback() {

Here, you apply the following styles:

  • box-border - include padding in the height and width.

  • flex, flex-col - a vertical flex layout.

  • p-m - medium padding.

  • gap-s - small gap between components.

  • w-full, h-full - full width and height.

It’s important to remember to call super.connectedCallback() whenever you override connectedCallback() to ensure that Lit initializes the component.

Save your view file. Start the development server with ./mvnw, if you don’t already have it running. You should now see this in your browser:

An empty list view with a filter text field