> Markdown version of [Classic Components](https://vaadin.com/docs/latest/flow/advanced/classic-components). Section index: [llms.txt](https://vaadin.com/docs/latest/flow/llms.txt)

# Upgrading from Vaadin 7 or 8 using Classic Components

<!-- vale Vaadin.ProductName = NO -->

One of the biggest challenges in migrating from Vaadin 7 or 8 to Vaadin Flow is that Flow is based on a different set of web components. The web components of Flow differ from their Vaadin 7 counterparts both in their API and behavior.

Classic Components is an add-on in Flow that provides a set of backwards-compatible components that ease migrating from Vaadin 7 or 8 to the latest Vaadin version. The API, behavior, and even the DOM structure of the components is made to mimic the Vaadin 7/8 components as much as possible.

Classic Components includes the following: HorizontalLayout, VerticalLayout, Panel, Label, GridLayout, and FormLayout. These components either lack counterparts in Flow entirely, or have significantly different APIs, requiring a lot of modifications when migrating. Classic Components also contain many abstract components from Vaadin 8 on which these components were based including `AbstractComponent`, `AbstractOrderedLayout`, and others.

To use Classic Components, only the imports for the supported components need to be changed to be able to use most of the same component features.

## <a id="license"></a>License

Classic Components is licensed under Commercial Vaadin Developer License 4.0 (CVDLv4) and part of the [Prime Subscription](https://vaadin.com/pricing). You’re asked to validate your license or start a trial period when you start using it.

## <a id="using-classic-components"></a>Using Classic Components

Classic Components is intended for migrating your project from Vaadin 7 or 8 to the latest Vaadin version. The pack should work with any Vaadin version after 14, but it’s tested against Vaadin 23. The recommendation is to migrate to Vaadin 23.

To use Classic Components, you first need to add the dependency to your project’s `pom.xml` or `build.gradle`, as follows:

- With Maven, add the pack dependency to `pom.xml`:

  `pom.xml`

  ```xml
  <dependencies>
      <!-| other dependencies -->
      <dependency>
          <groupId>com.vaadin</groupId>
          <artifactId>vaadin-classic-components-flow</artifactId>
      </dependency>
  </dependencies>
  ```

  After the dependency has been downloaded, you can start using the components by updating the component imports in your Java sources. For the components that are included in the pack, change the import statements to the corresponding Classic packages, for example, `com.vaadin.ui.VerticalLayout` to `com.vaadin.classic.v8.ui.VerticalLayout`.

### <a id="limitations-on-use-with-multiplatform-runtime-mpr"></a>Limitations On Use with Multiplatform Runtime (MPR)

Using Classic Components in combination with [Multiplatform Runtime (MPR)](https://vaadin.com/docs/latest/tools/mpr/overview.md) isn’t recommended for this version since it can lead to styling conflicts between the two.

### <a id="configuring-the-component-defaults-for-vaadin-7"></a>Configuring the Component Defaults for Vaadin 7

If you are upgrading from Vaadin 7, you can configure the Classic components to use the Vaadin 7 defaults with the system property `vaadin.classic-components.vaadin7defaults`. By introducing the property (no value needed), the Vaadin 7 defaults are used.

## <a id="included-components"></a>Included Components

Full API documentation is at <https://vaadin.com/api/com.vaadin/vaadin-classic-components-flow/>

### <a id="horizontallayout-and-verticallayout"></a>HorizontalLayout and VerticalLayout

Classic Components comes with HorizontalLayout and VerticalLayout designed to work and behave as close as possible to the corresponding components present in the Vaadin 7 or 8 versions. A few of the key features the components support include:

- **Expand Ratio**: children with "expand ratio" defined share the available space among them based on their ratios

- **Alignment**: each child can be aligned within its container (for example, top-left, middle-center, bottom-right, etc.)

- **Margin**: each side of the component’s margin can be enabled or disabled independently

The DOM structure of VerticalLayout and HorizontalLayout was developed to maintain the same set of elements and CSS classes (such as `v-verticallayout`/`v-horizontallayout`, `v-has-width`, `v-expand` and so on), so that a project being migrated from Vaadin 7 or 8 is likely to be able to use its current styles without changes. Class names defined in the layouts are added in the same way as before. For example, if `custom-style` is added to a `VerticalLayout` instance, both `custom-style` and `v-verticallayout-custom-style` are added to the DOM element.

### <a id="absolutelayout"></a>AbsoluteLayout

The Classic AbsoluteLayout resembles the Vaadin 8 version of AbsoluteLayout. It mimics HTML absolute positioning, letting you set an absolute position to its children.

> **Note: Missing features**
>
> `ContextClickEvent` and `LayoutClickListener` aren’t yet implemented in the Classic layouts.

HorizontalLayout and VerticalLayout are both Flow components, which means that they can be used together with any other component (Flow or other Classic Components).

#### <a id="deviations"></a>Deviations

Unlike in the previous implementation, the layouts use flexbox, since this provides a nicer, cleaner way to achieve the same behavior, especially for the "expand ratio" and alignment features. If any of the styles in the project being migrated rely on the previous implementation, they might not work as expected with the Classic layouts.

VerticalLayout and HorizontalLayout use Lumo variables to define their spacing and margin sizes.

| Valo Sass variable             | Lumo CSS variable |
| ------------------------------ | ----------------- |
| `$v-layout-spacing-horizontal` | `--lumo-space-m`  |
| `$v-layout-spacing-vertical`   | `--lumo-space-m`  |
| `$v-layout-margin-top`         | `--lumo-space-m`  |
| `$v-layout-margin-right`       | `--lumo-space-m`  |
| `$v-layout-margin-bottom`      | `--lumo-space-m`  |
| `$v-layout-margin-left`        | `--lumo-space-m`  |

### <a id="formlayout"></a>FormLayout

The Classic FormLayout resembles, as much as possible, the Vaadin 7 or 8 version of FormLayout. It shows all components added to it in a table with two columns. The left column contains the component’s caption (except for Checkbox). The components themselves appear stacked in the right column. If a component is marked as required, an asterisk is appended to its caption. As with HorizontalLayout and VerticalLayout, FlowLayout extends from the common superclass `AbstractOrderedLayout` and a selection of methods in classes with the same names from the V8 inheritance hierarchy.

> **Note: FormLayout is also in Flow**
>
> FormLayout is also a Flow component, which means it can be used together with any other component (Flow or other Classic Components).

### <a id="gridlayout"></a>GridLayout

The Classic GridLayout resembles the Vaadin 8 version of this component. It supports row and column spans, row and column expand ratios, and cell alignment.

### <a id="panel"></a>Panel

The Classic Panel component implements the same behavior as its counterpart in Vaadin 7/8 versions. It comes with updated styles based on the Lumo theme.

#### <a id="deviations-2"></a>Deviations

While most of the API comes from the Classic API, there are a few methods that are either not implemented or have their signature changed. For example, `setIcon(Resource)` is deprecated, but you can use `setIcon(Icon)` instead. However, `getIcon()` can’t be used, because it originally returns a `Resource` instance. Instead, the Classic `Panel` introduces `getIconAsIcon()`, which returns the `Icon` instance set previously. You can find the full list of unimplemented methods in ["Incompatible and Unsupported API and Migration Instructions"](#incompatible_api).

### <a id="label"></a>Label

The Classic Label component supports the same API as its counterpart in Vaadin 7/8. The only unsupported API is `setIcon()`.

As in Vaadin 7/8, it’s possible to change how the component interprets its contents. The content mode can be `ContentMode.HTML`, `ContentMode.PREFORMATTED`, and `ContentMode.TEXT`. The default is `ContentMode.TEXT`. The caption can be interpreted as HTML by setting the mode with `setCaptionAsHtml()`.

#### <a id="deviations-3"></a>Deviations

Unlike in the Label component in Vaadin 7/8, the wrapper element is always present, regardless of whether a caption is set or not. While this doesn’t affect the visual layout, it might break some CSS selectors. For example, it might break use of a CSS direct-child selector, such as `.my-class > .v-label`.

Another deviation from Vaadin 7/8 is when the content mode is set to `ContentMode.HTML`. Although the anchor and the image tags are still going to work, contrary to Vaadin 7/8, the script tags are completely removed from the content. The same applies when the caption is interpreted as HTML.

Also, as previously mentioned, there is no support for `setIcon()` at the moment.

## <a id="incompatible_api"></a>Incompatible and Unsupported API and Migration Instructions

Any API that was already deprecated in Vaadin 8 (or 7) **doesn’t exist** in the Classic Components. You should thus change any code that uses the deprecated APIs before starting the migration.

Any Classic Component API that can’t work or is obsolete in Vaadin Flow is included in the Classic Components as `@Deprecated` and **doesn’t do anything except log a warning in development mode**. This is done to make it’s faster to get the project to compile and run, and enables you to see the migration results sooner without having to comment out code.

This section goes through both the incompatible and the unsupported API introduced by each Classic Component class and how you could mitigate the situation if using that API in your project.

### <a id="the-component-interface"></a>The Component Interface

The base `Component` interface from Vaadin 7 and 8 is replaced by the abstract class `com.vaadin.flow.component.Component` in Flow. Most of the API is still the same or has changed only slightly. Classic Components introduces any missing API in the `AbstractComponent` class instead.

Table 1. `com.vaadin.ui.Component`

| Method signature                                                                                                                                               | Mitigation                                                                                                                                                                                                     |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `String getId()`                                                                                                                                               | **Return type changed to** `Optional<String>` by Flow `Component`                                                                                                                                              |
| `HasComponents getParent()`                                                                                                                                    | **Return type changed to** `Optional<Component>` by Flow `Component`                                                                                                                                           |
| `UI getUI()`                                                                                                                                                   | **Return type changed to** `Optional<UI>` by Flow `Component`                                                                                                                                                  |
| `String getCaption()` `void setCaption(String caption)`                                                                                                        | **Migrate**. Supported only by the classic `Label`; for other components, you need to move the text to another component, such as `Span` or `Div`. Replaced by `setLabel(String)` in field components in Flow. |
| `String getDescription()`                                                                                                                                      | **Remove/Migrate**. Not supported by Classic Components, and no direct replacement in Flow. Alternatives are [available in the Directory](https://vaadin.com/directory/search?keyword=tooltip).                |
| `Resource getIcon()` `setIcon(Resource icon)`                                                                                                                  | **Remove/Migrate**. Not supported by Classic Components. For Flow components, it depends on whether the component supports icons; for example, `Button` supports icons.                                        |
| `void readDesign(org.jsoup.nodes.Element design, DesignContext designContext)` `void writeDesign(org.jsoup.nodes.Element design, DesignContext designContext)` | **Remove**. You shouldn’t be even calling these methods as they are for Vaadin Designer integration only.                                                                                                      |

### <a id="the-abstractclientconnector-class"></a>The AbstractClientConnector Class

The Classic Components version of the class is in the `com.vaadin.classic.v8.server` package.

Table 2. `com.vaadin.server.AbstractClientConnector`

| Method signatures                                                                                                                                                                                                                                      | Mitigation                                                                                                                                                                                                                                                                                                                          |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `protected void fireEvent(EventObject event)`                                                                                                                                                                                                          | **Migrate**. Flow components' `ComponentEventBus` needs event object type to be `ComponentEvent<T>` instead. Use `getEventBus().fireEvent(event)` to fire the event. From outside the component, use `ComponentUtil::fireEvent()`.                                                                                                  |
| `protected void addExtension(Extension extension)` `Collection<Extension> getExtensions()` `void removeExtension(Extension extension)`                                                                                                                 | **Remove/Migrate**. Flow components can’t be extended with extensions. The method of migration depends on what the extension does. For pure server-side extensions, you can subclass the component. For extensions with client-side parts, you need to make a JavaScript file and call it from Java code inside the extended class. |
| `Registration addListener(Class<?> eventType, SerializableEventListener listener, Method method)` `protected Registration addListener(String eventIdentifier, Class<?> eventType, SerializableEventListener listener, Method method)`                  | **Migrate**. For external usage, use distinct *addXyzListener* API in the component or `ComponentUtil::addListener()` methods. For usage inside the component, this is replaced by Flow’s `ComponentEventListener` added to `ComponentEventBus`, which is only accessible inside the component.                                     |
| `protected void addMethodInvocationToQueue(String interfaceName, Method method, Object[] parameters)`                                                                                                                                                  | **Remove**. This method was only for internal usage; you shouldn’t be using it. It doesn’t apply for Flow.                                                                                                                                                                                                                          |
| `protected SharedState createState()` `protected SharedState getState()` `protected SharedState getState(boolean markAsDirty)` `Class<? extends SharedState> getStateType()` `protected void updateDiffstate(String propertyName, JsonValue newValue)` | **Remove/Migrate**. `SharedState` isn’t applicable to Flow; data is transferred through the [`Element` API](https://vaadin.com/docs/latest/flow/component-internals/element-api/properties-attributes.md) with properties and attributes instead.                                                                                   |
| `JsonObject encodeState()`                                                                                                                                                                                                                             | **Remove**. Internal method that doesn’t apply to Flow.                                                                                                                                                                                                                                                                             |
| `static Iterable<? extends ClientConnector> getAllChildrenIterable(ClientConnector connector)`                                                                                                                                                         | **Migrate**. Doesn’t apply directly to Flow; you can get child components with `Component::getChildren()`                                                                                                                                                                                                                           |
| `String getConnectorId()`                                                                                                                                                                                                                              | **Remove/Migrate**. Doesn’t apply to Flow. Manually set IDs can be used with `setId()` / `getId()`. Internally, Flow uses `StateNode::getId()` to track *nodes* between client and server.                                                                                                                                          |
| `ErrorHandler getErrorHandler()` `void setErrorHandler(ErrorHandler errorHandler)`                                                                                                                                                                     | **Migrate**. Flow doesn’t have a component-level error handler. Migrate to use `VaadinSession::setErrorHandler()` instead. Or, depending the type of error, you could use an [error view](https://vaadin.com/docs/latest/flow/routing/exceptions.md) instead.                                                                       |
| `Collection<?> getListeners(Class<?> eventType)`                                                                                                                                                                                                       | **Remove/Migrate**. No replacement available in Flow. Use the `fireEvent()` API from `ComponentEventBus` or `ComponentUtil` to notify all listeners.                                                                                                                                                                                |
| `protected Resource getResource(String key)` `protected void setResource(String key, Resource resource)`                                                                                                                                               | **Remove**. Not applicable in Flow.                                                                                                                                                                                                                                                                                                 |
| `ServerRpcManager<?> getRpcManager(String rpcInterfaceName)` `List<ClientMethodInvocation> retrievePendingRpcCalls()`                                                                                                                                  | **Remove**. Internal method that isn’t applicable in Flow.                                                                                                                                                                                                                                                                          |
| `protected <T extends ClientRpc> T getRpcProxy(Class<T> rpcInterface)` `protected <T extends ServerRpc> void registerRpc(T implementation)` `protected <T extends ServerRpc> void registerRpc(T implementation, Class<T> rpcInterfaceType)`            | **Remove/Migrate**. Not applicable in Flow. See documentation for [Remote Procedure Calls](https://vaadin.com/docs/latest/flow/component-internals/client-server-rpc.md).                                                                                                                                                           |
| `boolean handleConnectorRequest(VaadinRequest request, VaadinResponse response, String path)`                                                                                                                                                          | **Remove**. Internal method that shouldn’t even be used.                                                                                                                                                                                                                                                                            |
| `protected boolean hasListeners(Class<?> eventType)`                                                                                                                                                                                                   | **Migrate**. The event type is different; Classic Components have both `protected boolean hasListeners(Class<? extends ComponentEvent>)` and `hasListener(Class<? extends ComponentEvent>)`. Flow’s `Component` introduces the latter.                                                                                              |

### <a id="the-abstractcomponent-class"></a>The AbstractComponent Class

The Classic Components version of the class is in the `com.vaadin.classic.v8.ui` package.

Table 3. `com.vaadin.ui.AbstractComponent`

| Method signature                                                                                                          | Mitigation                                                                                                                                                                                                               |
| ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `protected void fireComponentErrorEvent()]`                                                                               | **Remove/Migrate**. Not supported by Classic Components and no direct replacement in Flow. The method of migration depends on what the error event was for.                                                              |
| `protected void focus()`                                                                                                  | **Migrate**. You need to first check whether the component implements `com.vaadin.flow.component.Focusable`, and then call `focus()` on it.                                                                              |
| `protected ActionManager getActionManager()`                                                                              | **Migrate**. Not supported by Classic Components. See [how to add shortcuts](https://vaadin.com/docs/latest/flow/component-internals/shortcut.md) in Flow.                                                               |
| `ErrorMessage getComponentError()` `ErrorMessage getErrorMessage()` `void setComponentError(ErrorMessage componentError)` | **Remove/Migrate**. Not supported by Classic Components and, in Flow, error messages are component-specific.                                                                                                             |
| `protected Collection<String> getCustomAttributes()`                                                                      | **Remove**. You shouldn’t even be calling this, as it was for Vaadin Designer integration only.                                                                                                                          |
| `boolean isCaptionAsHtml()` `void setCaptionAsHtml(boolean captionAsHtml)`                                                | **Migrate**. Supported only by the classic `Label` component. For other components, you need to move the text to another component, such as `Span` or `Div`. Replaced by `setLabel(String)` in field components in Flow. |
| `protected boolean isReadOnly()` `protected void setReadOnly(boolean readOnly)`                                           | **Remove/Migrate**. Not supported by Classic Components. In Flow, only field components can be read-only.                                                                                                                |
| `protected boolean isRequiredIndicatorVisible()` `protected void setRequiredIndicatorVisible(boolean visible)`            | **Remove/Migrate**. Not supported by Classic Components. In Flow, only field components can have a required indicator.                                                                                                   |
| `boolean isResponsive()` `void setResponsive(boolean responsive)`                                                         | **Remove**. Not supported by Classic Components or Flow components.                                                                                                                                                      |
| `void setDescription(String description)` `void setDescription(String description, ContentMode mode)`                     | **Remove/Migrate**. Not supported by Classic Components, and no direct replacement in Flow. Alternatives are [available in the Directory](https://vaadin.com/directory/search?keyword=tooltip).                          |

`CEBCC4DD-DDDD-44C3-ABA1-5DE81DF4891C`
