# WebContainer

> Embeds a native webview (HTML/JS) inside the UI — via the IWebView interface, platform-dependent.

Source: https://crossfly.dev/docs/ui/widgets/webcontainer — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# WebContainer

`WebContainer` is a widget that **embeds a native webview** (HTML/JavaScript content) inside your CrossFly UI. It is a thin *wrapper*: it draws nothing of its own — it delegates everything to the `IWebView` that the platform provides via `PlatformUtils.instance.createWebView()`. It serves to display a page, an HTML form, or a web panel as if it were an ordinary on-screen component.

> ⚠️ **Honesty about availability:** `WebContainer` **only works where a native `IWebView` exists** (Android, iOS, Desktop). **There is no concrete implementation of `IWebView` in this codebase nor in the Web/TeaVM target** — `createWebView()` returns `null` on unsupported platforms, and the `WebContainer` constructor then throws `UnsupportedOperationException`. On a Web/WebGL build, prefer opening an external page (`view(url)`) instead of embedding a webview.

> 🔴 · **Package:** `dev.crossfly.ui` · **Extends:** `Component` (implements `Runnable`) · **Delegates to:** `IWebView`

## When to use
- Display web content (HTML/JS) **inside** the app, on a platform with a native webview (Android/iOS/Desktop).
- Integrate an HTML form and capture the submission via `setFormSubmitListener`.

## When NOT to use
- For simple static content (text/image) → use the native widgets ([`chartview`](/docs/ui/widgets/chartview), labels, images) instead of loading a page.

## Appearance
`WebContainer` does not paint its own pixels: the system's native webview is overlaid on the component's area. Visibility is coordinated automatically in `onPaint` — the webview appears only when the parent window is on top (`isTopMost()`) and disappears otherwise.

## Complete example (copy, paste, and run)
`WebContainer` only works where a native `IWebView` exists. The example detects support with `PlatformUtils.instance.createWebView() != null` **before** creating the container (avoiding the constructor's `UnsupportedOperationException`) and, without support (e.g., the Web/TeaVM target), degrades by opening the page externally with `view(url)`.

```java
package com.exemplo;

import dev.crossfly.PlatformUtils;

import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;

/** Runnable main screen. Point the launcher (classname) and run: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      String url = "https://example.com";

      // Only create the WebContainer if the platform provides a native IWebView.
      if (PlatformUtils.instance.createWebView() != null)
      {
         WebContainer browser = new WebContainer();
         browser.show(url);
         add(LAY_FILL, browser);
      }
      else
      {
         // Web/TeaVM target (no embedded webview): opens the page externally.
         add(LAY_AUTO, new Label("Sem webview nativa — abrindo externamente…"));
         PlatformUtils.instance.view(url);
      }
   }
}
```

> The snippets below show **only the core** (what goes inside `onShow()`). To run them, place them in the `MainWindow` skeleton above.

## Basic usage
```java
WebContainer browser = new WebContainer();   // may throw UnsupportedOperationException
browser.show("https://example.com");
container.add(LAY_FILL, browser);
```

## Constructors
| Constructor | Description |
|---|---|
| `WebContainer()` | Obtains the native webview via `PlatformUtils.instance.createWebView()` and starts invisible. **Throws `UnsupportedOperationException`** if the platform does not provide an `IWebView`. |

## Properties and customization
| Method | Type | What it does |
|---|---|---|
| `show(String url)` | `void` | Loads and displays the URL in the webview. |
| `hide()` | `void` | Hides the webview while keeping the page state. |
| `setVisible(boolean)` | `void` | `true` = `show(null)` (keeps current URL/state); `false` = `hide()`. |
| `isVisible()` | `boolean` | Whether the webview is visible. |
| `evaluateJavaScript(String script)` | `void` | Executes JavaScript on the page. |
| `setFormSubmitListener(IWebView.FormSubmitListener)` | `void` | Registers a callback to capture HTML form submissions. |

> The `IWebView` requires operations to occur on the *render thread* (paint thread). Return to it with `Component.onUI(...)` if you are calling `show`/`evaluateJavaScript` from another thread.

## Callbacks and events
| Callback | When it fires |
|---|---|
| `IWebView.FormSubmitListener` (via `setFormSubmitListener`) | On submitting an HTML form inside the embedded page. |

> `WebContainer` **does not use** `onAction`/`onClick` — interaction happens inside the web page. The only app hook is the form submit listener.

## States
- **visible / hidden**: managed by `show`/`hide`/`setVisible` and, automatically, by the window position (the webview disappears when the parent window is not on top).
- **removed**: on `onRemove`, `view.removeView()` is called and the `IWebView` **cannot be reused** — to redisplay, create a new `WebContainer`.

### HTML form with submit capture (platform with webview)
```java
WebContainer form = new WebContainer();
form.setFormSubmitListener(dados -> processarEnvio(dados));  // IWebView.FormSubmitListener
form.show("https://meuservico/formulario.html");
container.add(LAY_FILL, form);
```

### Safe degradation on the Web target
```java
// On the Web/TeaVM build, createWebView() returns null and the constructor throws.
try {
   WebContainer c = new WebContainer();
   c.show("https://example.com");
   container.add(LAY_FILL, c);
} catch (UnsupportedOperationException e) {
   // No embedded webview: open the page externally.
   PlatformUtils.instance.view("https://example.com");
}
```

## Best practices
- Wrap the creation in a `try/catch` of `UnsupportedOperationException` to degrade gracefully on the Web target.

## Common mistakes
- **Creating `WebContainer` on an unsupported platform**: throws `UnsupportedOperationException`. Handle or detect it beforehand.
- **Reusing after `onRemove`**: the `IWebView` was discarded (`removeView()`); create a new instance.
- **Expecting to embed web on the Web/TeaVM target**: there is no implementation; embedding a webview ≠ being a web app. Use `view(url)`.

## See also
- Area guide: [`ui/`](/docs/ui) · Recipes: [`cookbook/`](/docs/cookbook)
- Concept (platforms, UI threading): [`concepts/`](/docs/concepts)
- Related components: [`locationview`](/docs/ui/widgets/locationview)
