Introduction
Fable.Ripple.Dom is an HTML DSL where signals bind straight to the DOM. There is no virtual tree: a signal knows which nodes read it, so a write updates those nodes and nothing else.
The demos on these pages are live. Press Run and the snippet is compiled by Fable in your browser; the Result tab is a real page - click its buttons, type in its fields, then edit the code and run it again.
Installation
dotnet add package Fable.Ripple.Dom --prerelease
A first component
A component is a function returning a DomItem. State lives in a Var; the view reads it, and the DOM follows every write:
open Fable.Ripple
open Fable.Ripple.Dom
let counter () =
let count = Var.create 0
Html.div
[
Html.button
[
on.click (fun _ -> count.Value <- count.Value + 1)
Html.text "Count"
]
Html.output count
]
Html.mount "app" counter |> ignore
Clicking the button writes count.Value. The <output> element reads count, so it is the only node that updates - no re-render of the component, no diff.
Mounting
Html.mount builds the view and renders it into the element with the given id:
Html.mount "app" counter |> ignore
It takes a unit -> DomItem, not a DomItem, so that the view is built inside the scope that owns it. It returns an IDisposable: disposing it removes the element and tears down every effect, computed and cleanup the view created. An app that runs until the page closes ignores the result.
Html.render returns the HTMLElement instead of mounting it, for you to place yourself:
open Browser
let element = Html.render (counter ())
document.body.appendChild element |> ignore