Alpine.js
FSharp.ViewEngine covers all 18 core directives in Alpine.js 3.15.12 and provides dedicated helpers for official plugins that expose HTML directives.
On this page
Overview
FSharp.ViewEngine covers all 18 core directives in Alpine.js 3.15.12 and provides dedicated helpers for official plugins that expose HTML directives.
Setup
Open the Alpine type to access Alpine directives:
open FSharp.ViewEngine
open type Html
open type AlpineModifier overloads accept ordered strings without leading periods. Directive arguments, such as event names and transition phases, are separate parameters:
button {
_xOn ("keydown", [ "enter"; "prevent"; "once" ], "save()")
}
div { _xTransition ("enter-start", "opacity-0 scale-90") }Directive arguments 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 Directives
x-data
Initialize a component's reactive state with _xData.
div {
_xData "{ open: false, count: 0 }"
button { _xOn ("click", "count++"); "Increment" }
span { _xText "count" }
}x-init
Run an expression when an element is initialized with _xInit.
div {
_xData "{ users: [] }"
_xInit "users = await (await fetch('/api/users')).json()"
}x-show
Toggle an element's display with _xShow. The important modifier applies display: none !important.
div { _xShow ([ "important" ], "open"); "Content" }x-bind
Bind an HTML attribute or property with _xBind. Use it for keyed x-for iterations instead of a plain by attribute.
template {
_xFor "item in items"
_xBind ("key", "item.id")
li { _xText "item.label" }
}x-on
Handle browser events with _xOn. Modifiers are emitted in their supplied order.
button {
_xOn ("click", [ "prevent"; "once" ], "save()")
"Save"
}x-text
Set textContent from an expression with _xText.
span { _xText "message" }x-html
Set innerHTML from an expression with _xHtml.
div { _xHtml "trustedHtml" }Security: Alpine inserts x-html content as HTML. Only use HTML created by trusted application code; never pass unsanitized user content.
x-model
Create two-way form bindings with _xModel. Modifiers use ordered strings.
input {
_type "search"
_xModel ([ "lazy"; "debounce.500ms" ], "query")
}x-modelable
Expose a component property to an outer x-model binding with _xModelable.
div {
_xData "{ value: 0 }"
_xModelable "value"
}x-for
Repeat a template with _xFor. Alpine requires x-for on a template with one root child.
template {
_xFor "item in items"
_xBind ("key", "item.id")
li { _xText "item.label" }
}x-transition
Apply Alpine's transition helper or explicit phase classes with _xTransition.
div {
_xShow "open"
_xTransition [ "duration.500ms"; "opacity" ]
}
div { _xTransition ("leave-end", "opacity-0 scale-90") }x-effect
Re-run an expression whenever its reactive dependencies change with _xEffect.
div { _xEffect "console.log(count)" }x-ignore
Prevent Alpine from initializing an element tree with _xIgnore. Use self to ignore only the element.
div { _xIgnore () }
div { _xIgnore [ "self" ] }x-ref
Name an element for access through $refs with _xRef.
input { _xRef "searchInput" }
button { _xOn ("click", "$refs.searchInput.focus()"); "Focus" }x-cloak
Hide an element until Alpine initializes with the presence-only _xCloak directive.
div { _xCloak; "Hidden until Alpine loads" }x-teleport
Move a template to the first element matching a CSS selector with _xTeleport.
template {
_xTeleport "body"
div { "Modal" }
}x-if
Conditionally add or remove a template's child from the DOM with _xIf.
template {
_xIf "open"
div { "Visible while open" }
}x-id
Create a scoped set of generated IDs with _xId.
div { _xId "['dropdown']" }Plugin Directives
Plugin helpers only render attributes; applications must install and register the corresponding Alpine package before Alpine starts. See the official plugin documentation for script and module setup.
x-mask
The Mask plugin formats input as the user types. Use _xMask for a fixed mask or _xMaskDynamic for an expression.
input { _xMask "99/99/9999" }
input { _xMaskDynamic "$money($input)" }x-intersect
The Intersect plugin runs an expression when an element enters or leaves the viewport.
div {
_xIntersect ([ "once"; "threshold.50" ], "visible = true")
}
div { _xIntersect ("leave", [ "full" ], "visible = false") }x-resize
The Resize plugin runs an expression when an element or document changes size.
div { _xResize "width = $width" }
div { _xResize ([ "document" ], "viewportWidth = $width") }x-collapse
The Collapse plugin animates an x-show element's height.
div {
_xShow "open"
_xCollapse [ "duration.500ms"; "min.50px" ]
}x-trap
The _xTrap helper requires Alpine's Focus plugin. Focus modifiers include inert, noscroll, noreturn, and noautofocus.
div {
_xShow "open"
_xTrap ([ "inert"; "noscroll" ], "open")
}Dependency: x-trap is provided by the Focus plugin, not Alpine core.
x-anchor
The _xAnchor helper positions an element relative to a reference and requires Alpine's Anchor plugin.
button { _xRef "trigger"; "Open" }
div {
_xAnchor ([ "bottom-start"; "offset.10"; "fixed" ], "$refs.trigger")
}Dependency: x-anchor is provided by the Anchor plugin, not Alpine core.
x-sort
The Sort plugin provides sortable containers, items, groups, configuration, handles, and ignored controls.
ul {
_xSort ([ "ghost" ], "handleSort($item, $position)")
_xSortGroup "tasks"
_xSortConfig "{ animation: 150 }"
li {
_xSortItem "task.id"
button { _xSortHandle; "Drag" }
button { _xSortIgnore; "Edit" }
}
}Plugins Without Directive Helpers
The Persist plugin exposes the $persist magic rather than an HTML directive, so no dedicated attribute helper is provided:
div { _xData "{ count: $persist(0) }" }The Morph plugin exposes the imperative Alpine.morph API rather than an HTML directive, so it also has no dedicated attribute helper.
Use the generic _x helper for third-party or future directives that are not yet represented:
div { _x ("third-party", "expression") }Trusted Expressions
Alpine directive values execute JavaScript expressions. FSharp.ViewEngine HTML-encodes attribute values, but encoding does not make untrusted expressions safe. Build expressions from trusted application code and do not interpolate user input into them.
Complete Example
A core-only disclosure component with keyboard handling and transitions:
div {
_xData "{ open: false }"
button {
_xOn ("click", "open = !open")
_xOn ("keydown", [ "escape"; "prevent" ], "open = false")
_xBind ("aria-expanded", "open")
"Toggle details"
}
div {
_xShow "open"
_xTransition [ "duration.200ms"; "opacity" ]
"Details"
}
}