> Note: Dash.NET is currently considered experimental. If your organization is interested in sponsoring Dash.NET, please get in touch.

# Advanced Callbacks

> To get the most out of this page, make sure you've read about Basic Callbacks in the Dash Fundamentals.

## Catching Errors with empty updates

In certain situations, you don't want to update the callback output. You can achieve this by simply not including it in the return of the callback function. `Callback.singleOut` is just an alias for calling `Callback.multiOut` with a single output.

    open Dash.NET
    open System

    let dslLayout =
        Html.div [
            Attr.children [
                Html.button [
                    Attr.id "show-secret"
                    Attr.children "Click here to see the content"
                ]
                Html.div [ Attr.id "body-div" ]
            ]
        ]

    let updateOutputsCallback =
        Callback.multiOut (
            "show-secret" @. (CustomProperty "n_clicks"),
            [ "body-div" @. Children ],
            fun (nClicks: Nullable<int>) ->
                match nClicks |> Option.ofNullable with
                | None -> []
                | Some n -> ["body-div" @. Children => "Elephants are the only animal that can't jump"]
        )

    [<EntryPoint>]
    let main args =
        DashApp.initDefault()
        |> DashApp.withLayout dslLayout
        |> DashApp.addCallback updateOutputsCallback
        |> DashApp.run args

## Displaying Errors with partial updates

This example illustrates how you can show an error while keeping the previous input, using the same technique to update only some of the callback outputs.

    open Dash.NET
    open System

    let dslLayout =
        Html.div [
            Attr.children [
                Html.p [ Attr.children "Enter a composite number to see its prime factors" ]
                Input.input "num" [
                    Input.Attr.inputType InputType.Number
                    Input.Attr.debounce true
                    Input.Attr.min 1
                    Input.Attr.step 1
                ]
                Html.p [ Attr.id "err"; Attr.style [ Css.color "red" ] ]
                Html.p [ Attr.id "out" ]
            ]
        ]

    let primeFactors num =
        let rec pf n i out =
            if i * i <= n then
                if n % i = 0 then
                    pf (n/i) i (i::out)
                else
                    if i = 2 then
                        pf n (i+1) out
                    else
                        pf n 2 out
            else
                n::out
        pf num 2 []

    let updateOutputsCallback =
        Callback.multiOut (
            "num" @. Value,
            [ "out" @. Children
              "err" @. Children ],
            fun (numberValue: Nullable<int>) ->
                match numberValue |> Option.ofNullable with
                | None ->
                    []
                | Some n ->
                    match primeFactors n with
                    | [] ->
                        []
                    | [f] ->
                        [ "out" @. Children => sprintf "%d is prime!" n ]
                    | factors ->
                        let factorsString =
                            factors
                            |> List.map string
                            |> List.reduce (sprintf "%s * %s")
                        [ "err" @. Children => sprintf "%d is %s" n factorsString ]
        )

    [<EntryPoint>]
    let main args =
        DashApp.initDefault()
        |> DashApp.withLayout dslLayout
        |> DashApp.addCallback updateOutputsCallback
        |> DashApp.run args

Sign up for Dash Club → Two free cheat sheets plus updates from Chris Parmer and Adam Schroeder delivered to your inbox every two months. Includes tips and tricks, community apps, and deep dives into the Dash architecture. Join now.

## When Are Callbacks Executed?

This section describes the circumstances under which the `dash-renderer` front-end client can make a request to the Dash back-end server (or the clientside callback code) to execute a callback function.

### When a Dash App First Loads

All of the callbacks in a Dash app are executed with the initial value of their inputs when the app is first loaded. This is known as the "initial call" of the callback. To learn how to suppress this behavior, see the documentation for the PreventInitialCall attribute of Dash callbacks.

It is important to note that when a Dash app is initially loaded in a web browser by the `dash-renderer` front-end client, its entire callback chain is introspected recursively.

This allows the `dash-renderer` to predict the order in which callbacks will need to be executed, as callbacks are blocked when their inputs are outputs of other callbacks which have not yet fired. In order to unblock the execution of these callbacks, first callbacks whose inputs are immediately available must be executed. This process helps the `dash-renderer` to minimize the time and effort it uses, and avoid unnecessarily redrawing the page, by making sure it only requests that a callback is executed when all of the callback's inputs have reached their final values.

Examine the following Dash app:

    open Dash.NET

    let dslLayout =
        Html.div [
            Attr.children [
                Html.button [ Attr.id "button_1"; Attr.children "Execute callbacks"; Attr.n_clicks 0 ]
                Html.div [ Attr.id "output_1"; Attr.children "callback not executed" ]
                Html.div [ Attr.id "output_2"; Attr.children "callback not executed" ]
            ]
        ]

    let changeTextCallback =
        Callback.multiOut (
            "button_1" @. (CustomProperty "n_clicks"),
            [ "output_1" @. Children
              "output_2" @. Children ],
            fun (nClicks: int) ->
                match nClicks with
                | 0 ->
                    [ "output_1" @. Children => sprintf "n_clicks is None"
                      "output_2" @. Children => sprintf "n_clicks is None" ]
                | _ ->
                    [ "output_1" @. Children => sprintf "n_clicks is %d" nClicks
                      "output_2" @. Children => sprintf "n_clicks is %d" nClicks ]
            , PreventInitialCall = false
        )

    [<EntryPoint>]
    let main args =
        DashApp.initDefault()
        |> DashApp.withLayout dslLayout
        |> DashApp.addCallback changeTextCallback
        |> DashApp.run args

Notice that when this app is finished being loaded by a web browser and ready for user interaction, the `Html.div` components do not say "callback not executed" as declared in the app's layout, but rather "n_clicks is None" as the result of the `changeTextCallback` callback being executed. This is because the "initial call" of the callback occurred with `n_clicks` having the value of `0`. `Attr.n_clicks` needs to be set to some initial value (in this case 0), otherwise dash will throw an exception.

### As a Direct Result of User Interaction

Most frequently, callbacks are executed as a direct result of user interaction, such as clicking a button or selecting an item in a dropdown menu. When such interactions occur, Dash components communicate their new values to the `dash-renderer` front-end client, which then requests that the Dash server execute any callback function that has the newly changed value as input.

If a Dash app has multiple callbacks, the `dash-renderer` requests callbacks to be executed based on whether or not they can be immediately executed with the newly changed inputs. If several inputs change simultaneously, then requests are made to execute them all.

Whether or not these requests are executed in a synchronous or asynchronous manner depends on the specific setup of the Dash back-end server. If it is running in a multi-threaded environment, then all of the callbacks can be executed simultaneously, and they will return values based on their speed of execution. In a single-threaded environment however, callbacks will be executed one at a time in the order they are received by the server.

In the example application above, clicking the button results in the callback being executed.

### As an Indirect Result of User Interaction

When a user interacts with a component, the resulting callback might have outputs that are themselves the input of other callbacks. The `dash-renderer` will block the execution of such a callback until the callback whose output is its input has been executed.

Take the following Dash app:

    open Dash.NET
    open System

    let dslLayout =
        Html.div [
            Attr.children [
                Html.button [ Attr.id "button_1"; Attr.children "Execute fast callback" ]
                Html.button [ Attr.id "button_2"; Attr.children "Execute slow callback" ]
                Html.div [ Attr.id "output_1"; Attr.children "callback not executed" ]
                Html.div [ Attr.id "output_2"; Attr.children "callback not executed" ]
                Html.div [ Attr.id "output_3"; Attr.children "callback not executed" ]
            ]
        ]

    let updateFastCallback =
        Callback.singleOut (
            "button_1" @. (CustomProperty "n_clicks"),
            "output_1" @. Children,
            fun (nClicks: int) ->
                let now = DateTimeOffset.Now
                "output_1" @. Children => sprintf "In the fast callback it is %s" (now.ToString())
        )

    let updateSlowCallback =
        Callback.singleOut (
            "button_2" @. (CustomProperty "n_clicks"),
            "output_2" @. Children,
            fun (nClicks: int) ->
                async { do! Async.Sleep 5000 } |> Async.RunSynchronously
                let now = DateTimeOffset.Now
                "output_2" @. Children => sprintf "In the slow callback it is %s" (now.ToString())
        )

    let updateThirdCallback =
        Callback.singleOut (
            [ "output_1" @. Children
              "output_2" @. Children ],
            "output_3" @. Children,
            fun (o1: obj) (o2: obj) ->
                let now = DateTimeOffset.Now
                "output_3" @. Children => sprintf "In the third callback it is %s" (now.ToString())
        )

    [<EntryPoint>]
    let main args =
        DashApp.initDefault()
        |> DashApp.withLayout dslLayout
        |> DashApp.addCallback updateFastCallback
        |> DashApp.addCallback updateSlowCallback
        |> DashApp.addCallback updateThirdCallback
        |> DashApp.run args

The above Dash app demonstrates how callbacks chain together. Notice that if you first click "execute slow callback" and then click "execute fast callback", the third callback is not executed until after the slow callback finishes executing. This is because the third callback has the second callback's output as its input, which lets the `dash-renderer` know that it should delay its execution until after the second callback finishes.

### When Dash Components Are Added to the Layout

It is possible for a callback to insert new Dash components into a Dash app's layout. If these new components are themselves the inputs to other callback functions, then their appearance in the Dash app's layout will trigger those callback functions to be executed.

In this circumstance, it is possible that multiple requests are made to execute the same callback function. This would occur if the callback in question has already been requested and its output returned before the new components which are also its inputs are added to the layout.

## Prevent Callback Execution Upon Initial Component Render

You can use the `PreventInitialCall` attribute to prevent callbacks from firing when their inputs initially appear in the layout of your Dash application.

This attribute applies when the layout of your Dash app is initially loaded, and also when new components are introduced into the layout when a callback has been triggered.

    open Dash.NET
    open System

    let dslLayout =
        Html.div [
            Attr.children [
                Html.button [ Attr.id "button_1"; Attr.children "Execute callbacks" ]
                Html.div [ Attr.id "output_1"; Attr.children "callback not executed" ]
                Html.div [ Attr.id "output_2"; Attr.children "callback not executed" ]
                Html.div [ Attr.id "output_3"; Attr.children "callback not executed" ]
                Html.div [ Attr.id "output_4"; Attr.children "callback not executed" ]
            ]
        ]

    let updateFirstCallback =
        Callback.multiOut (
            "button_1" @. (CustomProperty "n_clicks"),
            [ "output_1" @. Children
              "output_2" @. Children ],
            fun (nClicks: int) ->
                let now = DateTimeOffset.Now
                [ "output_1" @. Children => sprintf "In the first callback it is %s" (now.ToString())
                  "output_2" @. Children => sprintf "In the first callback it is %s" (now.ToString()) ]
            , PreventInitialCall = true
        )

    let updateSecondCallback =
        Callback.singleOut (
            "output_2" @. Children,
            "output_3" @. Children,
            fun (o: obj) ->
                async { do! Async.Sleep 5000 } |> Async.RunSynchronously
                let now = DateTimeOffset.Now
                "output_3" @. Children => sprintf "In the second callback it is %s" (now.ToString())
            , PreventInitialCall = true
        )

    let updateThirdCallback =
        Callback.singleOut (
            [ "output_2" @. Children
              "output_3" @. Children ],
            "output_4" @. Children,
            fun (o1: obj) (o2: obj) ->
                let now = DateTimeOffset.Now
                "output_4" @. Children => sprintf "In the third callback it is %s" (now.ToString())
            , PreventInitialCall = true
        )

    [<EntryPoint>]
    let main args =
        DashApp.initDefault()
        |> DashApp.withLayout dslLayout
        |> DashApp.addCallback updateFirstCallback
        |> DashApp.addCallback updateSecondCallback
        |> DashApp.addCallback updateThirdCallback
        |> DashApp.run args

However, the above behavior only applies if both the callback output and input are present in the app layout upon initial load of the application.

It is important to note that `PreventInitialCall` will not prevent a callback from firing in the case where the callback's input is inserted into the layout as the result of another callback after the app initially loads unless the output is inserted alongside that input!

In other words, if the output of the callback is already present in the app layout before its input is inserted into the layout, `PreventInitialCall` will not prevent its execution when the input is first inserted into the layout.

Consider the following example:

    open Dash.NET

    let dslLayout =
        Html.div [
            Attr.children [
                Location.location "url" [ Location.Attr.pathname "/" ]
                Html.div [ Attr.id "layout-div" ]
                Html.div [ Attr.id "content" ]
            ]
        ]

    let updatePageCallback =
        Callback.singleOut (
            "url" @. (CustomProperty "pathname"),
            "content" @. Children,
            fun (pathname: string) ->
                let layout =
                    Html.div [
                        Attr.children [
                            Input.input "input" [
                                Input.Attr.value "Hello World"
                            ]
                            Html.div [ Attr.id "output" ]
                        ]
                    ]
                "content" @. Children => layout
            , PreventInitialCall = false
        )

    let updateOutputCallback =
        Callback.singleOut (
            "input" @. Value,
            "output" @. Children,
            fun (value: string) ->
                "output" @. Children => value
            , PreventInitialCall = true
        )

    let updateLayoutCallback =
        Callback.singleOut (
            "input" @. Value,
            "layout-div" @. Children,
            fun (value: string) ->
                "layout-div" @. Children => value
            , PreventInitialCall = true
        )

    [<EntryPoint>]
    let main args =
        DashApp.initDefault()
        |> DashApp.withLayout dslLayout
        |> DashApp.addCallback updatePageCallback
        |> DashApp.addCallback updateOutputCallback
        |> DashApp.addCallback updateLayoutCallback
        |> DashApp.run args

In this case, `PreventInitialCall` will prevent the `updateOutputCallback` callback from firing when its input is first inserted into the app layout as a result of the `updateLayoutCallback` callback. This is because both the input and output of the callback are already contained within the app layout when the callback executes.

However, because the app layout contains only the output of the callback, and not its input, `PreventInitialCall` will not prevent the `updateLayoutCallback` callback from firing. Dash has to assume that the input is present in the app layout when the app is initialized. From the perspective of the output element in this example, the new input component is handled as if an existing input had been provided a new value, rather than treating it as initially rendered.