Loading States

Loading Component

The dcc.Loading component displays a spinner when the components it wraps are in a loading state.
Internally, Dash updates the dcc.Loading component when the loading state of the components it wraps changes.

open System.Threading

open Microsoft.Extensions.Logging
open Giraffe
open Dash.NET.Giraffe

open Dash.NET
open Dash.NET.DCC

let layout =
    Html.div [
        Attr.children [
            Html.h3 [ Attr.value "Edit text input to see loading state" ]
            Input.input "ls-input-1" [ Input.Attr.value "Input triggers local spinner" ]
            Loading.loading "ls-loading-1" [
                Loading.Attr.children [ Html.div [ Attr.id "ls-loading-output-1" ] ]
                Loading.Attr.loadingType Loading.LoadingType.Default
            ]
            Html.div [
                Attr.children [
                    Input.input "ls-input-2" [ Input.Attr.value "Input triggers nested spinner" ]
                    Loading.loading "ls-loading-2" [
                        Loading.Attr.children [
                            Html.div [ Attr.children [ Html.div [ Attr.id "ls-loading-output-2" ]]]
                        ]
                        Loading.Attr.loadingType Loading.LoadingType.Circle
                    ]
                ]
            ]
        ]
    ]

let inputTriggerSpinnerCallback =
    let outputTarget = "ls-loading-output-1" @. Children
    Callback.singleOut ("ls-input-1" @. Value, outputTarget,
        (fun (value: obj) ->
            Thread.Sleep 1000
            outputTarget => value
        )
    )

let inputTriggerNestedCallback =
    let outputTarget = "ls-loading-output-2" @. Children
    Callback.singleOut ("ls-input-2" @. Value, outputTarget,
        (fun value ->
            Thread.Sleep 1000
            outputTarget => value
        )
    )

[<EntryPoint>]
let main argv =
    let dashApp =
        DashApp.initDefault()
        |> DashApp.appendCSSLinks [ "./assets/custom.css" ]
        |> DashApp.withLayout layout
        |> DashApp.addCallbacks [ inputTriggerSpinnerCallback; inputTriggerNestedCallback ]

    let config =
        { HostName = "localhost"
          LogLevel = LogLevel.Debug
          ErrorHandler = (fun ex -> text ex.Message) }

    DashApp.run [||] config dashApp

Edit text input to see loading state

Please also check out the docs for the Loading component for more information on how to use the Loading component.

Check Loading States From Components

Aside from using the Loading component, you can check if a certain component
(either from Dash.NET.DCC or Dash.NET.Html) is loading by checking the
data-dash-is-loading attribute set on that component’s HTML output. This means that
you can target those components yourself with CSS, and create your own custom loading
for them. Here’s an example of what that could look like:

open System.Threading

open Microsoft.Extensions.Logging
open Giraffe
open Dash.NET.Giraffe

open Dash.NET
open Dash.NET.DCC

let layout =
    Html.div [
        Attr.children [
            Html.div [ Attr.id "cls-output-1" ]
            Input.input "cls-input-1" [ Input.Attr.value "Input triggers local spinner" ]
            Html.div [
                Attr.children [
                    Html.div [ Attr.id "cls-output-2" ]
                    Input.input "cls-input-2" [ Input.Attr.value "Input triggers nested spinner" ]
                ]
            ]
        ]
    ]

let inputTriggerSpinnerCallback =
    let outputTarget = "cls-output-1" @. Children
    Callback.singleOut ("cls-input-1" @. Value, outputTarget,
        (fun (value: obj) ->
            Thread.Sleep 1000
            outputTarget => value
        )
    )

let inputTriggerNestedCallback =
    let outputTarget = "cls-output-2" @. Children
    Callback.singleOut ("cls-input-2" @. Value, outputTarget,
        (fun value ->
            Thread.Sleep 1000
            outputTarget => value
        )
    )

[<EntryPoint>]
let main argv =
    let dashApp =
        DashApp.initDefault()
        |> DashApp.appendCSSLinks [ "./assets/custom.css" ]
        |> DashApp.withLayout layout
        |> DashApp.addCallbacks [ inputTriggerSpinnerCallback; inputTriggerNestedCallback ]

    let config =
        { HostName = "localhost"
          LogLevel = LogLevel.Debug
          ErrorHandler = (fun ex -> text ex.Message) }

    DashApp.run [||] config dashApp

You could target all components in the layout above that are loading using the following CSS:

*[data-dash-is-loading="true"]{
    visibility: hidden;
}
*[data-dash-is-loading="true"]::before{
    content: "Loading...";
    display: inline-block;
    color: magenta;
    visibility: visible;
}

You can also target any other HTML attributes using CSS.
To target a specific class use the following CSS:

*[class="output-example-loading"][data-dash-is-loading="true"]{
    visibility: hidden;
}
*[class="output-example-loading"][data-dash-is-loading="true"]::before{
    content: "Loading...";
    display: inline-block;
    color: magenta;
    visibility: visible;
}