> Markdown version of [Flow Integration](https://vaadin.com/docs/next/hilla/guides/flow-integration). Section index: [llms.txt](https://vaadin.com/docs/next/hilla/llms.txt)

# Flow Integration

A Flow component can be used in Hilla views by implementing the `WebComponentExporter` class and using the resulting web component. The `WebComponentExporter` class can target any Flow component.

Here’s an example of such a component:

```java
public class CustomComponent extends Div {

    public CustomComponent(@Autowired GreetService service) {
        Button button = new Button("Say hello", e -> {
            Notification.show("Hello!");
        });

        add(button);
    }
}
```

That component can then be turned into a web component like so:

```java
public class MyFlowComponentExporter
        extends WebComponentExporter<CustomComponent> {

    public static final String TAG = "my-flow-component";

    public MyFlowComponentExporter() {
        super(TAG);
    }

    @Override
    protected void configureInstance(WebComponent<CustomComponent> webComponent,
                                     CustomComponent component) {
    }
}
```

For more information, see [Creating an Embedded Vaadin Application](https://vaadin.com/docs/next/flow/integrations/embedding/exporter.md).

> **Note:** The `WebComponentExporter` needs to have a public no-argument constructor. Otherwise, it won’t be instantiated or generated.

To add the exported web component to a Hilla view, import the `reactElement` function from Flow and create a `React.DOMElement` with the same tag name as you used for the `WebComponentExporter` (i.e., `TAG` in the previous example) in a React component. Then use the resulting React component inside the view like this:

TSX

```jsx
import { VerticalLayout } from '@vaadin/react-components/VerticalLayout.js';
import { reactElement } from 'Frontend/generated/flow/Flow'; // (1)

function MyFlowComponent() {
  return reactElement('my-flow-component'); // (2)
}

export default function HillaView() {
  return (
    <>
      <VerticalLayout className={'centered-content'}>
        <h3>Hilla View</h3>
        <MyFlowComponent/> // (3)
      </VerticalLayout>
    </>
  );
}
```

1. Import the `reactElement` function.

2. Return an instance of the custom element you exported, using the same tag name, from a React component.

3. Use the React component in your view.

## <a id="using-attributes"></a>Using Attributes

You can add attributes for the element by passing in a `Properties` object with `string` value pairs to the `reactElement` function.

You can use this when the exported web component exposes properties to the client.

Custom Properties for Flow WebComponent

```jsx
import { VerticalLayout } from '@vaadin/react-components/VerticalLayout.js';
import { reactElement } from 'Frontend/generated/flow/Flow';
import React from 'react';

function MyFlowComponent() {
  // Create element with property hellomsg
  return reactElement('my-flow-component', {
    hellomsg: 'Hi from the client!'
  });
}

export default function HillaView() {
  return (
    <>
      <VerticalLayout className={'centered-content'}>
        <h3>Hilla View</h3>
        <MyFlowComponent/>
      </VerticalLayout>
    </>
  );
}
```

You can also link the properties to the React component properties using a custom properties type:

Custom Properties with Attribute Link

```jsx
import { VerticalLayout } from '@vaadin/react-components/VerticalLayout.js';
import { reactElement } from 'Frontend/generated/flow/Flow';
import React from 'react';

type MyProperties = {
  hellomsg: string
}

function MyFlowComponent(props: MyProperties) {
  // Create element with property hellomsg
  return reactElement('my-flow-component', {
    hellomsg: props.hellomsg
  });
}

export default function HillaView() {
  return (
    <>
      <VerticalLayout className={'centered-content'}>
        <h3>Hilla View</h3>
        <MyFlowComponent hellomsg={'Hi from the client!'}/>
      </VerticalLayout>
    </>
  );
}
```

In this way, changing the attribute also updates the web component property value.

The following example shows the corresponding server-side code for the web component property:

Web Component with Exposed Properties

```java
public class MyFlowComponentExporter
        extends WebComponentExporter<CustomComponent> {

    public static final String TAG = "my-flow-component";

    public MyFlowComponentExporter() {
        super(TAG);
        addProperty("hellomsg", "Hello!")
            .onChange(CustomComponent::setHelloMessage);
    }

    @Override
    protected void configureInstance(WebComponent<CustomComponent> webComponent,
                                     CustomComponent component) {
    }
}
```

Flow Component with Property

```java
public class CustomComponent extends Div {
    String helloMessage;

    public CustomComponent(@Autowired GreetService service) {
        Button button = new Button("Say hello", e -> {
            Notification.show(helloMessage);
        });

        add(button);
    }

    public void setHelloMessage(String helloMessage) {
        this.helloMessage = helloMessage;

    }
}
```

## <a id="onload-event-for-webcomponent"></a>Onload Event for WebComponent

Loading the `WebComponent` script can take some time, depending on the network. Therefore, it might be good to show a loading indicator so the user knows to wait.

It’s possible to listen to the `onload` event for the `WebComponent` script so that the loading element can be removed when the script is finished loading.

The `reactElement` accepts an `onload` callback function as the third parameter. An `onerror` callback function can be set as the fourth parameter. If an `onerror` callback isn’t given, an error is logged into the console if a web component script fails to load.

Loading Indicator Example

```jsx
import { VerticalLayout } from '@vaadin/react-components/VerticalLayout.js';
import { reactElement } from 'Frontend/generated/flow/Flow';
import React from 'react';

type MyProperties = {
  hellomsg: string
}

function MyFlowComponent(props: MyProperties) {
  // Create element with property hellomsg
  return reactElement('my-flow-component',
    undefined,
    () => document.getElementById('loading')?.remove()
  );
}

export default function HillaView() {
  return (
    <>
      <VerticalLayout className={'centered-content'}>
        <h3>Hilla View</h3>
        <!-- Placeholder element for MyFlowComponent script loading -->
        <div id={"loading"}>Loading script...</div>
        <MyFlowComponent hellomsg={'Hi from the client!'}/>
      </VerticalLayout>
    </>
  );
}
```

`920dc03d-5eb4-4826-8934-4416b58a9a3e`
