fsbolero / Bolero

Bolero brings Blazor to F# developers with an easy to use Model-View-Update architecture, HTML combinators, hot reloaded templates, type-safe endpoints, advanced routing and remoting capabilities, and more.
https://fsbolero.io
Apache License 2.0
1.06k stars 53 forks source link

Custom Bolero node #343

Open xperiandri opened 9 months ago

xperiandri commented 9 months ago

Can I define an async Bolero node similar to

namespace SkillGro.Teams.Client.Interop

open System.Threading.Tasks
open Microsoft.AspNetCore.Components
open Bolero.Html
open SkillGro.Teams.Client.Interop.TeamsSDK

#nowarn "46"

type TeamsView() =
    inherit Bolero.Component()

    /// <summary>
    /// The main template for your application.
    /// </summary>
    /// <remarks>
    /// This template is rendered when the application has been properly initialized by this component.
    /// </remarks>
    [<Parameter>]
    member val InTeams : RenderFragment<TeamsContextReader> = Unchecked.defaultof<_> with get, set

    /// <summary>
    /// A template that you can use to provide alternative content in cases when the Teams host is not available.
    /// </summary>
    /// <remarks>
    /// This template is typically rendered when the application is not loaded by Teams.
    /// </remarks>
    [<Parameter>]
    member val StandAlone : RenderFragment = Unchecked.defaultof<_> with get, set

    [<CascadingParameter>]
    member val private TeamsContext : Task<TeamsContextReader voption> = Unchecked.defaultof<_> with get, set

    member private _.StateHasChangedInternal() = base.StateHasChanged()

    override component.OnInitializedAsync() = task {
        match! component.TeamsContext with
        | ValueSome ctx -> component.StateHasChangedInternal()
        | ValueNone -> ()
    }

    override component.Render() =
        if component.TeamsContext.IsCompleted then
            match component.TeamsContext.Result with
            | ValueSome ctx -> component.InTeams.Invoke(ctx) |> fragment
            | ValueNone -> component.StandAlone |> fragment
        else
            component.StandAlone |> fragment
Tarmil commented 9 months ago

What you have seems pretty okay, are you looking for a simpler way to do it?

In .NET 8 there's "streaming rendering" that automates this, but we'll need to convert Bolero's server-side rendering from the current custom renderer to Blazor 8's SSR to be able to use it.

xperiandri commented 9 months ago

but we'll need to convert Bolero's server-side rendering from the current custom renderer to Blazor 8's SSR to be able to use it

Will you work on that?

are you looking for a simpler way to do it?

If a more type-safe or Bolero-native way exists, then I would try

Tarmil commented 9 months ago

Will you work on that?

I've started looking into it, yes.

If a more type-safe or Bolero-native way exists, then I would try

It needs to use a dedicated component anyway. You could make the component generic instead of necessarily using TeamsContextReader to stay type safe, and write a wrapper function that calls comp<TeamsView> with the right parameters, but I think that's as good as you can make it.