Documentation

Documentation versions (currently viewingVaadin 23)
New Acceleration Kits: Observability Kit, SSO Kit, and Swing Kit. Read the blog post.

Creating a Component Container

Creating a component that can contain other components.

This section demonstrates how to create a Component container.

A component container is a component to which you can add other components. A container is typically created through a generic public API.

Example: Simple component container.

@Tag("div")
public class MyComponentContainer extends Component
        implements HasComponents {
}
  • The HasComponents interface provides add(Component…​) and remove(Component…​) methods to handle attaching component elements to the MyComponentContainer root element (<div> in this example).

Implementing a Custom Add Method

If necessary, you can implement your own add method. For example, you might a different kind of API or have a complex internal element hierarchy.

Example: Implementing a custom method to add components to a container.

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

    public void add(Component child) {
        getElement().appendChild(child.getElement());
    }
}

Attaching Child Components to the DOM

When a child component is added to a container component, the container must attach the child to the DOM. This is the only absolute requirement for a container component.

In the previous example, the child element attaches to the root element (as HasComponents does). As an alternative, you can place each child in a wrapper element or use a more complex element hierarchy if necessary.

Example: Wrapping a child component in an element wrapper.

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

    public void add(Component child) {
        Element childWrapper = ElementFactory
                .createDiv();
        childWrapper.appendChild(child.getElement());
        getElement().appendChild(childWrapper);
    }
}

Using Component Hierarchy Methods

Component hierarchy methods, such as getChildren() and getParent(), work automatically for container components, because they are implemented based on the element hierarchy. These methods also work if you have placed the child components in wrapper elements.

You can add a similar method to remove components.

Example: Using the removeFromParent() method to detach a component.

public void remove(Component child) {
    Element wrapper = child.getElement().getParent();
    wrapper.removeFromParent();
}
Note
Removing child components
When you use the remove() method, you can’t assume that a component is always removed. You can detach a child element manually through the Element API, for example, by using the Element.removeFromParent() method. Another way is to add the child element to another component. For example, the Element.appendChild() method moves the element to the new parent from the old one, if it’s still attached.
Tip
Detecting when a child component is removed
If you need to know when a child component is removed, add a detach listener to it using the Component.addDetachListener() method.

Enabling and Disabling Container Components

When you set a container component as disabled, all child components are automatically also set as disabled, and updates from the client to the server are blocked.

Components that implement the HasEnabled interface are updated accordingly to reflect the disabled state in the UI. This usually means setting the component’s disabled attribute.

If your container includes elements or components that don’t implement the HasEnabled interface, you can still visually update them to reflect the disabled state in the UI by overriding the onEnabledStateChanged() method.

Example: Setting a component as disabled by overriding the onEnabledStateChanged() method.

@Override
public void onEnabledStateChanged(boolean enabled) {
    super.onEnabledStateChanged(enabled);
    if (enabled) {
        childElement.removeAttribute("disabled");
    } else {
        childElement.setAttribute("disabled", true);
    }
}
  • You only need to override the onEnabledStateChanged() method to update the visual aspect of the element. When the container is disabled, communication from the client to the server is blocked, regardless if you override the method.

  • It’s important to call super.onEnabledStateChanged(enabled) when overriding. This is because it contains common logic that applies to all components in connection with the enabled state.

  • The onEnabledStateChanged() method is called every time the enabled state changes. This applies whether the state change is by direct calls to setEnabled(), by calling setEnabled() on a parent container, or by attaching the component to, or detaching it from, a disabled container.

See Enabled State for more.

B669953B-4FB8-4B0F-920A-67AAC655BBD2