> Markdown version of [Basics](https://vaadin.com/docs/latest/flow/component-internals/basic). Section index: [llms.txt](https://vaadin.com/docs/latest/flow/llms.txt)

# Vaadin Component Basics

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.

## <a id="defining-a-root-element"></a>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](https://vaadin.com/docs/latest/flow/component-internals/element-api.md) reference guide for more information.

Example 1. Creating a `TextField` component based on an `<input>` element

`TextField.java`

```java
package com.vaadin.demo.reference.componentinternals.basics;

import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.Tag;

@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.

### <a id="using-multiple-elements"></a>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 `LabeledTextField` component with `<input>` and `<label>` elements inside a `<div>` root element

`LabeledTextField.java`

```java
package com.vaadin.demo.reference.componentinternals.basics;

import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.dom.Element;

@Tag("div")
public class LabeledTextField extends Component {

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

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

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

```html
<div>
    <label></label>
    <input>
</div>
```

### <a id="extending-a-component"></a>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 `LabeledTextField` component created above

`CustomTextField.java`

```java
package com.vaadin.demo.reference.componentinternals.basics;

import com.vaadin.flow.dom.Element;

public class CustomTextField extends LabeledTextField {

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

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

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

```html
<div>
    <label></label>
    <input>
    <span></span>
</div>
```

### <a id="composite-components"></a>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 `CompositeTextField` component with `Input` and `NativeLabel` components inside a `Div` root component

`CompositeTextField.java`

```java
package com.vaadin.demo.reference.componentinternals.basics;

import com.vaadin.flow.component.Composite;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Input;
import com.vaadin.flow.component.html.NativeLabel;

public class CompositeTextField extends Composite<Div> {

    private final NativeLabel label;
    private final Input input;

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

        // Users of CompositeTextField can't access the div directly since
        // getContent() is protected.
        var div = getContent();
        div.add(label, input);
    }

    // Declare public API here.
}
```

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

```html
<div>
    <label></label>
    <input>
</div>
```

## <a id="creating-a-java-api"></a>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](https://vaadin.com/docs/latest/flow/component-internals/properties.md) reference guide.

- Events and event listeners for reacting to user actions. This is covered in the [Declaring and Firing Component Events](https://vaadin.com/docs/latest/flow/component-internals/events.md) 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](https://vaadin.com/docs/latest/flow/component-internals/client-server-rpc.md) reference guide.

Example 5. An API for getting and setting the `value` property, and reacting to value changes

`TextField.java`

```java
@Synchronize("change")
public String getValue() {
    return getElement().getProperty("value");
}

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

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

## <a id="lifecycle-callbacks"></a>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.

### <a id="attach-to-ui"></a>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

`UserNameLabel.java`

```java
package com.vaadin.demo.reference.componentinternals.basics;

import com.vaadin.flow.component.AttachEvent;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.Tag;

@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.

### <a id="detach-from-ui"></a>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

`ShoppingCartSummaryLabel.java`

```java
package com.vaadin.demo.reference.componentinternals.basics;

import java.util.EventObject;
import java.util.function.Consumer;

import com.vaadin.flow.component.AttachEvent;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.DetachEvent;
import com.vaadin.flow.component.Tag;

@Tag("div")
public class ShoppingCartSummaryLabel extends Component {

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

    @Override
    protected void onAttach(AttachEvent attachEvent) {
        // This assumes the session already contains a ShopEventBus
        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.

### <a id="attach-scoped-setup-and-cleanup"></a>Attach-Scoped Setup and Cleanup (new in V25.3)

When the cleanup in `onDetach()` only undoes what `onAttach()` did, the two halves can be kept together with `whenAttached()`. The handler runs every time the component is attached — immediately, if the component is already attached — and the `Registration` it returns runs when the component is detached again.

Example 8. Subscribing to an event bus in `whenAttached()` and unsubscribing in the returned registration

`CartSummaryWhenAttached.java`

```java
package com.vaadin.demo.reference.componentinternals.basics;

import java.util.EventObject;
import java.util.function.Consumer;

import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.Tag;

@Tag("div")
public class CartSummaryWhenAttached extends Component {

    public CartSummaryWhenAttached() {
        whenAttached(ui -> {
            // This assumes the session already contains a ShopEventBus
            var eventBus = ui.getSession().getAttribute(ShopEventBus.class);
            Consumer<EventObject> handler = this::onCartSummaryUpdate;
            eventBus.register(handler);

            return () -> eventBus.unregister(handler);
        });
    }

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

Because the cleanup closes over the local variables of the handler, no field is needed to carry state from an attach to the matching detach. The handler receives the `UI` the component was attached to, and it can return `null` when there is nothing to clean up.

Removing the returned registration removes the handler and also runs any cleanup still pending from the latest attach. An exception thrown by the handler is propagated to the caller, whereas one thrown by the cleanup is passed to the session error handler, so that a failing cleanup does not prevent the rest of the detach handling from running.

The same method is available on the element level as `Element.whenAttached()`. Both are public, so they can also be used from the outside to hook into the life cycle of another component.

## <a id="setting-id"></a>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 9. Setting a component `Id`

`SetIdView.java`

```java
var component = new ShoppingCartSummaryLabel();
component.setId("my-component");
```

`2E20FB94-B5FD-4105-B53B-3EECA329EFF3`
