Skip to main content

Datastar

FSharp.ViewEngine covers all 31 attributes in the stable Datastar 1.0.2 reference through the Datastar type.

On this page

Overview

FSharp.ViewEngine covers all 31 attributes in the stable Datastar 1.0.2 reference through the Datastar type.

Setup

Open the Datastar type to access Datastar attributes:

open FSharp.ViewEngine
open type Html
open type Datastar

Modifier overloads accept an ordered list of modifier strings without the leading __. Modifier arguments follow the modifier name after a period:

input {
    _dataBind ("query", [ "event.input" ])
    _dataOn ("input", [ "debounce.200ms" ], "@get('/search')")
}

Keys, event names, and modifier strings become part of the HTML attribute name. Treat them as trusted application tokens; FSharp.ViewEngine does not validate or encode attribute names.

Core Attributes

data-signals

Create or patch signals with _dataSignals. Use object syntax for multiple signals, keyed syntax for one signal, and modifiers for casing or if-missing behavior.

div {
    _dataSignals "{count: 0, name: 'World'}"
    _dataSignals ("page", [ "ifmissing" ], "1")
}

data-bind

Create a two-way binding with _dataBind. Keyed bindings are presence-only; modifiers can select a property and synchronization events.

input {
    _type "search"
    _dataBind ("query", [ "prop.value"; "event.input.change" ])
}

data-computed

Create a read-only computed signal with _dataComputed.

div {
    _dataComputed ("double", "$count * 2")
    _dataComputed "{greeting: () => 'Hello, ' + $name}"
}

data-effect

Run a side-effect expression on initialization and whenever its signal dependencies change with _dataEffect.

div { _dataEffect "console.log($count)" }

data-show

Show or hide an element based on an expression with _dataShow.

div {
    _dataShow "$count > 0"
    "Count is positive"
}

data-text

Set an element's text content reactively with _dataText.

span { _dataText "$count" }

data-attr

Set one or more HTML attributes reactively with _dataAttr.

button {
    _dataAttr ("disabled", "$loading")
    _dataAttr "{'aria-busy': $loading}"
}

data-class

Toggle one or more classes with _dataClass. Keyed modifiers can override casing behavior.

div {
    _dataClass ("font-bold", "$strong")
    _dataClass ("my-class", [ "case.camel" ], "$active")
}

data-style

Set one or more inline style properties reactively with _dataStyle.

div {
    _dataStyle ("background-color", "$error ? 'red' : 'green'")
    _dataStyle "{display: $visible ? 'flex' : 'none'}"
}

data-init

Run an expression when an attribute is initialized with _dataInit. Delay and view-transition modifiers are supported.

div {
    _dataInit ([ "delay.500ms"; "viewtransition" ], "$ready = true")
}

data-on

Handle DOM events with _dataOn. Modifier order is preserved in the generated attribute name.

button {
    _dataOn ("click", [ "once"; "prevent" ], "$count++")
    "Increment"
}

data-on-intersect

Run an expression when an element enters or exits the viewport with _dataOnIntersect.

div {
    _dataOnIntersect ([ "once"; "threshold.25" ], "$visible = true")
}

data-on-interval

Run an expression on an interval with _dataOnInterval.

div {
    _dataOnInterval ([ "duration.500ms.leading" ], "$count++")
}

data-on-signal-patch

Run an expression when signals are patched with _dataOnSignalPatch. Timing modifiers can delay, debounce, or throttle the listener.

div {
    _dataOnSignalPatch ([ "debounce.500ms" ], "console.log(patch)")
}

data-on-signal-patch-filter

Filter signal patches using include and exclude regular expressions with _dataOnSignalPatchFilter.

div {
    _dataOnSignalPatchFilter "{include: /^count$/, exclude: /temp$/}"
}

data-indicator

Create a signal that tracks in-flight fetch requests with the presence-only _dataIndicator helper.

button {
    _dataIndicator "fetching"
    _dataOn ("click", "@get('/endpoint')")
    _dataAttr ("disabled", "$fetching")
}

data-ref

Create a signal containing a reference to an element with the presence-only _dataRef helper.

input { _dataRef "searchInput" }

data-json-signals

Render signals as JSON for debugging with _dataJsonSignals. Filters and terse output are optional.

pre { _dataJsonSignals () }
pre { _dataJsonSignals ([ "terse" ], "{include: /counter/}") }

data-ignore

Prevent Datastar from processing an element tree with _dataIgnore. Use the self modifier to ignore only the element.

div { _dataIgnore () }
div { _dataIgnore [ "self" ] }

data-ignore-morph

Prevent an element and its children from being processed during morphing with _dataIgnoreMorph.

div { _dataIgnoreMorph }

data-preserve-attr

Preserve one or more existing attribute values during morphing with _dataPreserveAttr.

details {
    _open true
    _dataPreserveAttr "open class"
}

Pro Attributes

Datastar Pro attributes require a Datastar Pro license. They are included as convenience helpers but are not part of the free core bundle.

data-animate

Animate a named element attribute reactively with the keyed _dataAnimate helper.

div {
    _dataAnimate ("opacity", "$visible ? 1 : 0")
}

data-custom-validity

Set a form control's custom validation message with _dataCustomValidity.

input {
    _dataBind "email"
    _dataCustomValidity "$email.includes('@') ? '' : 'Enter a valid email'"
}

data-match-media

Keep a signal synchronized with a media query using _dataMatchMedia.

div {
    _dataMatchMedia ("is-dark", "'prefers-color-scheme: dark'")
    _dataComputed ("theme", "$isDark ? 'dark' : 'light'")
}

data-on-raf

Run an expression on every animation frame with _dataOnRaf. Throttle modifiers can limit updates.

canvas {
    _dataOnRaf ([ "throttle.10ms" ], "draw()")
}

data-on-resize

Run an expression when an element's dimensions change with _dataOnResize.

div {
    _dataOnResize ([ "debounce.10ms" ], "$width = el.offsetWidth")
}

data-persist

Persist signals to local or session storage with _dataPersist. Use _dataPersistFilter for a default-key filter object.

div { _dataPersist () }
div { _dataPersist "settings" }
div { _dataPersist ("settings", [ "session" ]) }
div { _dataPersistFilter "{include: /theme/}" }

data-query-string

Synchronize signals with query-string parameters using _dataQueryString.

div {
    _dataQueryString ([ "filter"; "history" ], "{include: /search|page/}")
}

data-replace-url

Replace the browser URL without reloading using an evaluated expression passed to _dataReplaceUrl.

div { _dataReplaceUrl "`/page${$page}`" }

data-scroll-into-view

Scroll an element into view with _dataScrollIntoView. Behavior, alignment, and focus are controlled by modifiers.

div { _dataScrollIntoView () }
div { _dataScrollIntoView [ "smooth"; "vcenter"; "focus" ] }

data-view-transition

Set an element's view-transition-name reactively with _dataViewTransition.

div { _dataViewTransition "$transitionName" }

Trusted Expressions

Datastar expressions can execute JavaScript and backend actions. Attribute values are HTML-encoded by FSharp.ViewEngine, but encoding does not make untrusted expressions safe. Build expressions from trusted application code and never interpolate untrusted input into them.

Complete Example

An active search form using signals, binding, modifiers, an indicator, and a backend action:

div {
    _dataSignals ("query", [ "ifmissing" ], "''")
    _dataIndicator "searching"

    input {
        _type "search"
        _dataBind "query"
        _dataOn ("input", [ "debounce.200ms" ], "@get('/api/search')")
    }

    span { _dataShow "$searching"; "Searching..." }
    div { _id "search-results" }
}