Read layout state and drive content from Dash callbacks.

Callbacks

Read layout state and drive content from Dash callbacks.


Reading the live model

Set useStateForModel=False and the layout round-trips through Dash, so you can read the current model from any callback via Input("your-dock-id", "model"). Rearrange the panels below and watch the JSON update.

# File: docs/callbacks/example.py

import json

from dash import html, dcc, callback, Input, Output
import flexlayout_dash as dfl

# With useStateForModel=False the layout round-trips through Dash, so you can
# read the live model from a callback. Drag a tab or move a splitter and watch
# the JSON update below.
model = {
    "global": {"tabEnableClose": False, "tabEnableFloat": True},
    "layout": {
        "type": "row",
        "children": [
            {
                "type": "tabset",
                "weight": 50,
                "children": [{"type": "tab", "name": "Left", "id": "callbacks-left"}],
            },
            {
                "type": "tabset",
                "weight": 50,
                "children": [{"type": "tab", "name": "Right", "id": "callbacks-right"}],
            },
        ],
    },
}


def _panel(text):
    return html.Div(text, style={"padding": "16px"})


component = html.Div(
    [
        dfl.DashFlexLayout(
            id="callbacks-dock",
            model=model,
            useStateForModel=False,
            style={"height": "320px"},
            children=[
                dfl.Tab(id="callbacks-left", children=[_panel("Rearrange these panels…")]),
                dfl.Tab(id="callbacks-right", children=[_panel("…and the model JSON below updates live.")]),
            ],
        ),
        html.P("Live model (read via Input('callbacks-dock', 'model')):",
               style={"fontWeight": 600, "marginTop": "12px"}),
        dcc.Markdown(id="callbacks-model-json"),
    ]
)


@callback(
    Output("callbacks-model-json", "children"),
    Input("callbacks-dock", "model"),
)
def show_model(model):
    text = json.dumps(model, indent=2)
    if len(text) > 1400:
        text = text[:1400] + "\n  ... (truncated)"
    return f"```json\n{text}\n```"

How it stays callback-friendly

flexlayout-dash renders each tab's children through a React portal into a stable container, so your tab content stays mounted across internal FlexLayout changes (tab switches, splitter drags). That keeps callbacks bound to elements inside tabs working.

As of 1.1.0, echoes of FlexLayout's own internal model changes no longer recreate the layout model, so stateful tab content (canvases, editors, in-progress drags) is not re-mounted on tab switch or splitter drag — only a model your own callbacks write rebuilds it. setProps still fires on every change, so Input(dock, "model") keeps working.

Tip: keep tabs mounted

For callbacks bound to elements inside tabs, keep every tab mounted by setting "tabEnableRenderOnDemand": False in the model's global section.


Source: /callbacks

Note for AI agents: This is the static, prerendered view of an interactive Dash application served because we detected a non-JS user agent. Full prose docs: