Docs

Documentation versions (currently viewingVaadin 25 (prerelease))

Vaadin Component Basics

Creating a Vaadin component with a client-side element and a server-side Java API.

All Vaadin components consist of a client-side HTML element and a server-side Java component. The server-side components extend the com.vaadin.flow.component.Component base class. Vaadin provides support for keeping the client-side element and server-side component in sync.

Defining a Root Element

Every component is associated with a root Element, which is accessible from the Component.getElement() method. The @Tag annotation specifies the HTML tag name of the root element.

You use the Element API to interact with the client-side elements, for example by manipulating attributes, properties and styles, and reacting to events. See the Element API reference guide for more information.

Example 1. Creating a TextField component based on an <input> element
Source code
Java
@Tag("input")
public class TextField extends Component {

    public TextField(String value) {
        getElement().setProperty("value",value);
    }
}

You can use predefined constants in the @Tag annotation. For example, the @Tag("input") annotation is equivalent to @Tag(Tag.INPUT). Most tag names have a constant, but not all.

Using Multiple Elements

A component can consist of multiple elements in the DOM tree. In this case, the root element is still defined using the @Tag annotation, and other elements are created and appended to the root element using the Element API.

Example 2. Creating a TextField component with <input> and <label> elements inside a <div> root element
Source code
Java
@Tag("div")
public class TextField extends Component {

    private final Element labelElement = new Element("label");
    private final Element inputElement = new Element("input");

    public TextField() {
        getElement().appendChild(labelElement, inputElement);
    }
}

This generates the following DOM-tree structure in the browser:

Source code
HTML
<div>
    <label></label>
    <input>
</div>

Extending a Component

If you extend an existing component, the root element is inherited from the parent component class. You can still use the Element API to manipulate the root element or create and append child elements. However, you don’t need to use the @Tag annotation in this case.

Example 3. Extending the TextField component created above
Source code
Java
public class CustomTextField extends TextField {

    private final Element errorElement = new Element("span");

    public CustomTextField() {
        super();
        getElement().appendChild(errorElement);
    }
}

This generates the following DOM-tree structure in the browser:

Source code
HTML
<div>
    <label></label>
    <input>
    <span></span>
</div>

Composite Components

When you create a new component by combining existing components, you should extend the Composite<T> class, where T is the type of the root component. This does not affect the DOM structure, but prevents users of your component from accessing the API of the root component directly.

Example 4. Creating a TextField component with Input and NativeLabel components inside a Div root component
Source code
Java
public class TextField extends Composite<Div> {

    private final NativeLabel label;
    private final Input input;

    public TextField(String labelText, String value) {
        label = new NativeLabel();
        label.setText(labelText);
        input = new Input();
        input.setValue(value);

        getContent().add(label, input);
    }
}

// In later code:
TextField textField = new TextField("Name", "John Doe");
// textField does not expose any of the methods of Div.

This generates the following DOM-tree structure in the browser:

Source code
HTML
<div>
    <label></label>
    <input>
</div>

Creating a Java API

The Element API provides low-level access to the client-side element. You typically want to create a higher-level Java API that hides these details from the users of your component.

A Vaadin component API consists of:

  • Properties for accessing and setting values. This is covered in the Component Properties reference guide.

  • Events and event listeners for reacting to user actions. This is covered in the Declaring and Firing Component Events reference guide.

  • Other methods that act on the component. Some of them may use the Element API to call JavaScript functions on the client side. This is covered in the Remote Procedure Calls reference guide.

Example 5. An API for getting and setting the value property, and reacting to value changes
Source code
Java
@Synchronize("change")
public String getValue() {
    return getElement().getProperty("value");
}

public void setValue(String value) {
    getElement().setProperty("value", value);
    fireEvent(new ValueChangeEvent(this, false));
}

public Registration addValueChangeListener(
        ComponentEventListener<ValueChangeEvent> listener) {
    return addListener(ValueChangeEvent.class, listener);
}

Lifecycle Callbacks

The topmost component in any component hierarchy is the UI instance. The UI may represent an entire browser window (or tab), or some part of an HTML page where a Vaadin application is embedded.

Attach to UI

Whenever a component is added to a UI, either directly or indirectly through another component, it is considered to be attached to the UI. When a component is removed from the UI, it is considered to be detached from the UI.

The Component class provides an onAttach() method that is called when the component has been attached to a UI. Override this method to perform initialization that requires the component to be attached. The default implementation is empty, so you don’t need to call super.onAttach() unless you are extending another component class that requires it.

Example 6. Getting a session attribute in the onAttach() method
Source code
Java
@Tag("div")
public class UserNameLabel extends Component {

    @Override
    protected void onAttach(AttachEvent attachEvent) {
        // This assumes the username has been stored in the session after login
        String userName = (String) attachEvent.getSession().getAttribute("username");
        getElement().setText("Hello %s, weclome back!".formatted(userName));
    }
}

You can also use the Component.addAttachListener() method to register an attach listener instead of overriding the onAttach() method. The listener is invoked after the onAttach() method. This is useful when you want to add attach behavior to an existing component without creating a subclass.

Detach from UI

The Component class also provides a onDetach() method that is called right before the component is detached from the UI. Override this method to perform cleanup, for example to release resources that were acquired in the onAttach() method. The default implementation is empty, so you don’t need to call super.onDetach() unless you are extending another component class that requires it.

Example 7. Subscribing to an event bus in the onAttach() method and unsubscribing in the onDetach() method
Source code
Java
@Tag("div")
public class ShoppingCartSummaryLabel extends Component {

    private final Consumer<EventObject> eventHandler = this::onCartSummaryUpdate;

    @Override
    protected void onAttach(AttachEvent attachEvent) {
        var eventBus = attachEvent.getSession().getAttribute(ShopEventBus.class);
        eventBus.register(eventHandler);
    }

    @Override
    protected void onDetach(DetachEvent detachEvent) {
        var eventBus = detachEvent.getSession().getAttribute(ShopEventBus.class);
        eventBus.unregister(eventHandler);
    }

    private void onCartSummaryUpdate(EventObject event) {
        // update cart summary ...
    }
}

interface ShopEventBus {
    void register(Consumer<EventObject> eventHandler);
    void unregister(Consumer<EventObject> eventHandler);
}

You can also use the Component.addDetachListener() method to register a detach listener instead of overriding the onDetach() method. The listener is invoked after the onDetach() method. This is useful when you want to add detach behavior to an existing component without creating a subclass.

Setting Id

You can set an Id for any component. The Id is passed to the client side as the id of the corresponding element. However, an Id must be unique within the page, as it can be used to select the element in JavaScript code or CSS rules.

Example 8. Setting a component Id
Source code
Java
component.setId("my-component");

2E20FB94-B5FD-4105-B53B-3EECA329EFF3