Skip to content

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

Terminal
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
Edit this page