.NET WASM is still loading. You can interact in this page after it's fully loaded.

Current page is prerendered.

Htmx

For what is htmx please check their doc, here in Fun.Blazor we use it for pull down blazor content by its request and inject into somewhere.

It is recommend to use it together with custom element, so we can get real time interactive with websocket which has full power of blazor when needed.

There is also a blog which is related to this topic.

How to use

Register the components:

services.AddRazorComponents()
services.AddServerSideBlazor(fun options -> 
	// for using html.customElement
	options.RootComponents.RegisterCustomElementForFunBlazor(Assembly.GetExecutingAssembly()))
services.AddFunBlazorServer()

...
app.MapRazorComponents()
app.MapRazorComponentsForSSR(Assembly.GetExecutingAssembly(), enableAntiforgery = true)
app.MapCustomElementsForSSR(Assembly.GetExecutingAssembly(), enableAntiforgery = true)

The simple way to serve a page

app.MapFunBlazor(fun _ -> html' {
    head {
        ...
        CustomElement.lazyBlazorJs ()
    }
    body {
        // We can use html.customElement to prerender something and connect to server with websocket at some point
        html.customElement (
            ComponentAttrBuilder<PostLikesSurvey>().Add((fun x -> x.post_id), post.Id),
            renderAfter = RenderAfter.InViewport
        )
        // For more complex cases, we can use htmx to fetch customElement and then connect to server with websocket
        div {
            hxTrigger hxEvt.intersect
            hxGetCustomElement (QueryBuilder<PostLikesSurvey>().Add((fun x -> x.post_id), post.Id))
            hxSwap_outerHTML
        }
        // We can also just request any blazor component as a static dom content and inject at some point based on htmx
        div {
            hxTrigger hxEvt.intersect
            hxGetComponent (QueryBuilder<PostComment>().Add((fun x -> x.PostId), post.Id))
            hxSwap_outerHTML
        }
        // Or prerender directly and later on the PostComment itself will have htmx integration
        html.blazor (ComponentAttrBuilder<PostComment>().Add((fun x -> x.PostId), post.Id))
        // script for htmx
        script { src "https://unpkg.com/htmx.org@1.9.9" }
    }
})
[<FunBlazorCustomElement>]
type PostLikesSurvey() =
    inherit FunComponent()

    [<Parameter>]
    member val post_id = "" with get, set

    override this.Render() = fragment {
        ...
    }

type PostComment() as this =
    inherit FunComponent()

    [<Parameter>]
    member val PostId = Guid.Empty with get, set

    [<Parameter>]
    member val Comment = "" with get, set

    override _.Render() = form {
        hxSwap_outerHTML
        hxPostComponent typeof<PostComment>
        // You can use below method to save the current state in the form, so the browser will always have the latest state
        // And later you can override it, because server will only take the last value for the same key
        html.createHiddenInputs this
        html.blazor<AntiforgeryToken> ()
        textarea {
            name (nameof this.Comment)
            value this.Comment
        }
        button {
            type' InputTypes.Submit
            "Add"
        }
    }