# Integrations

## data-\*

[DataStar](https://data-star.dev/) is a hypermedia framework that builds interactive web
applications by extending HTML with declarative **`data-*` attributes**. Rather than introducing a
template language or a client-side component model, it enhances standard HTML with reactive
behavior, making it a natural fit for HtmlFlow.

The **`htmlflow-datastar`** module extends **`htmlflow-kotlin`** with a **type-safe DSL** for DataStar's
attributes and expressions. Instead of writing `data-*` attributes and JavaScript expressions as
strings, they are represented through Kotlin APIs that provide compile-time validation, IDE
completion, and seamless integration with the existing HtmlFlow Kotlin DSL.

### 1. Dependencies

### 1. Dependency

Add the **`htmlflow-datastar`** module to your project.

```groovy
implementation 'com.github.xmlet:htmlflow-datastar:1.3.0-alpha'
```

### 2. Type-safe signals and attributes

DataStar manages reactive state through **`signals`**, which are created and consumed by different **`data-*`** attributes. In HtmlFlow Datastar, a signal
is created once using **`dataSignal`** and represented as a typed **`Signal<T>`** object that can be reused throughout the view. Instead of referencing signals
through string-based **`data-*`** attributes, builders such as **`dataText`**, **`dataShow`**, and **`dataClass`** accept **`Signal<T>`** objects directly, providing
type safety, IDE completion, and consistent signal references. As shown below, the **`count`** signal is created once and then passed to **`dataText`** to display its value.

```kotlin
div {
  val count: Signal<Int> = dataSignal("count", 0)
  div {
     span {
      attrId("counter")
      dataText { +count }
    }
  }
}
```

This produces the equivalent DataStar markup:

```html
<div data-signals:count="0">
  <span id="counter" data-text="$count"></span>
</div>
```

Reusing the same **`Signal<T>`** object avoids misspelled signal names and keeps references consistent.

### 3. Type-safe events and modifiers

User interactions are defined through **`data-on:*`** attributes. HtmlFlow Datastar exposes these as type-safe
event builders, allowing the event type (such as **`Click`** or **`Input`**), the action, and any modifiers to be expressed
using Kotlin APIs instead of manually constructing strings.

In the following example, the input field is bound to the **`search`** signal. Every **`Input`** event triggers a GET request, but
only after the user has stopped typing for **200 ms**, thanks to the **`debounce`** modifier. This reduces the number of requests sent
while the user is typing and improves the overall user experience.

Notice that the DataStar **`get`** action accepts a Kotlin function reference. During rendering, this reference is resolved
to the URL declared in the function's route annotation, eliminating the need to hardcode endpoint paths and ensuring they remain
synchronized with the server-side route definitions.

```kotlin
div {
  val search: Signal<String> = dataSignal("search", "")
  input {
    attrType(EnumTypeInputType.TEXT)
    attrPlaceholder("Search...")
    dataBind(search)
    dataOn(Input) {
      get(::search)
      modifiers { debounce(200.milliseconds) }
    }
  }
}
```

Which produces:

```html
<div data-signals:search="''">
  <input type="text" placeholder="Search..." data-bind:search data-on:input__debounce="@get('/examples/search')" />
</div>
```

Typed events and modifiers eliminate invalid event names and malformed modifier syntax.

### 4. Type-safe expressions

Many DataStar attributes accept JavaScript-like expressions. Instead of writing these expressions as
strings, HtmlFlow Datastar represents them as Kotlin objects that can be combined using familiar
operators such as **`and`**, **`or`**, and **`not`**.

In the following example, **`dataIndicator`** creates a signal named **`_fetching`**. The leading **`_`**
follows a DataStar convention indicating that the signal is local and is therefore not sent to the server
when an HTTP request is made. The signal's value is automatically set to **`true`** while a request is in
progress and back to **`false`** when the request completes.

The **`dataAttr`** attribute binds the value of any HTML attribute to an expression, keeping it automatically
synchronized with the expression's result. In this case, binding the button's disabled attribute to **`_fetching`**
ensures that the button is disabled while the request is in progress.

The same signal is also used in the **`dataOn`** expression to prevent multiple requests from being sent if the user
clicks the button before the browser has applied the disabled attribute. This provides an additional safeguard against duplicate requests.

```kotlin
button {
  val fetching: Signal<Boolean> = dataIndicator("_fetching")
  dataAttr("disabled") { +fetching }
  dataOn(Click) {
      !fetching and get(::clickToLoadMore)
  }
  text("Load More")
}
```

Which generates:

```html
<button
  data-indicator:_fetching
  data-attr:disabled="$_fetching"
  data-on:click="!$_fetching && @get('/examples/click_to_load/more')"
>
  Load More
</button>
```

Expressions can be composed and refactored using Kotlin operators instead of string concatenation.

**HtmlFlow Datastar** generates standard **DataStar** HTML, enabling developers to build reactive user interfaces
declaratively with a fully **type-safe** Kotlin DSL while preserving compatibility with the **DataStar** runtime.

## http4k

[http4k](https://www.http4k.org/) is a Kotlin HTTP toolkit built on the idea of handlers as plain
functions (`(Request) -> Response`). HtmlFlow plugs into http4k's templating SPI through the
**`htmlflow-view-loader`** module (`com.github.xmlet:htmlflow-view-loader`), so HtmlFlow views can
be used wherever http4k expects a template engine: alongside, or instead of, Pebble, Thymeleaf,
or Handlebars.

The view loader does **convention-based resolution**: you expose your views as
`HtmlView<MyViewModel>` members (a `val` property or a function), point the loader at a package, and
it builds a registry that maps each model type to its view (matching superclasses and interfaces as
a fallback). The result is a `(ViewModel) -> String` function, which is exactly http4k's
`TemplateRenderer`.

### 1. Dependencies

Add the Kotlin DSL, the view loader, and http4k's template core:

```groovy
implementation 'com.github.xmlet:htmlflow-kotlin:5.0.4'
implementation 'com.github.xmlet:htmlflow-view-loader:5.0.4'
implementation 'org.http4k:http4k-template-core'
```

### 2. A view model and its view

The model implements http4k's `ViewModel`; the view is an `HtmlView` typed by that model. To find a
view, the loader scans each class in the package for a zero-argument member that returns an
`HtmlView` — a `val` property or a function both work. It just needs an instance to read that member
from, and it tries several ways to get one: a Kotlin `object`, a top-level (file-level) declaration,
a class with a no-argument constructor, a companion object, a `getInstance()` singleton, or a
constructor that takes an `HtmlFlow.ViewFactory`. A Kotlin `object` is the simplest, so this example
uses one:

```kotlin
import htmlflow.*
import org.http4k.template.ViewModel
import org.xmlet.htmlapifaster.body
import org.xmlet.htmlapifaster.h1

data class Greeting(val name: String) : ViewModel

object Views {
  val greeting: HtmlView<Greeting> = HtmlFlow.view {
    it.html {
      body {
        dyn { model: Greeting -> h1 { text("Hello, ${model.name}!") } }
      }
    }
  }
}
```

### 3. Build the renderer

`ClasspathLoader(ViewModel::class.java).createRenderer(package)` scans the package and returns a
renderer that resolves the right view from the model's type at call time:

```kotlin
import htmlflow.viewloader.ClasspathLoader
import org.http4k.template.TemplateRenderer

val renderer: TemplateRenderer =
  ClasspathLoader(ViewModel::class.java).createRenderer("com.example.views")
```

### 4. Wire it into an http4k handler

Use http4k's `viewModel` body lens to render a model straight into a response. No explicit view
lookup is needed. The loader picks `Views.greeting` because the model is a `Greeting`:

```kotlin
import org.http4k.core.*
import org.http4k.core.ContentType.Companion.TEXT_HTML
import org.http4k.template.viewModel

val htmlView = Body.viewModel(renderer, TEXT_HTML).toLens()

val app: HttpHandler = { _: Request ->
  Response(Status.OK).with(htmlView of Greeting("World"))
}
```

Set `hotReload = true` on `createRenderer(...)` during development to re-scan views on each render
(this also disables pre-encoding); keep it `false` (the default) in production so views are
pre-encoded once and cached. See [Core Concepts → Configuring Views](https://htmlflow.org/docs/core-concepts#configuring-views).
