plotly-dash

How to Reference a Nested Component Property in 'Running' Parameter of Dash Callback


Is there a way to directly reference a nested property of a component when using the "Running" parameter of plotly-dash? For example:

Without nested direct reference (works - but must provide the entire multi-part property):

@app.callback(Output("graph1", "children"), Input("w1_radioSelect", "value"), 
              running=[
                          Output("checkbox_selector", "options"),
                          [{"label": "checkbox label", "value":"value", "disabled":True}, {...Remaining Options' Key-Value Pairs...}],
                          [{"label": "checkbox label", "value":"value", "disabled":True}, {...Remaining Options' Key-Value Pairs...}]
                      ]
              )

With nested direct reference (doesn't work - looking for some type of similar syntax that does...?)

@app.callback(
                Output("graph1", "children"), Input("w1_radioSelect", "value"), 
                running=[Output("checkbox_selector", "options[0].disabled"),True, False]
             )

I tried a few variations of the above with no luck.

As is probably obvious from the example, this is specifically in reference to the dcc.Checklist item. I don't think there is any other way to disable a particular option (other than to set the "disabled" key in the corresponding options list entry to True), but someone please correct me if I'm wrong on that account. Also, as far as I can tell, there is no "disabled" parameter available for the checklist in its entirety.

Additional Reference: See Section "Updating Component Properties when a Callback is Running"


Solution

  • You could use client side callbacks to disable all of the checkboxes at once. Here is an example where all of the checkboxes nested under the div element with the id checkbox_selector will be disabled when the radio buttons are changed. Note that the callback needs an output to satisfy Dash.

    # Disables all of the checkboxes
    app.clientside_callback(
        """
        function(value) {
            const checkboxes = document.querySelectorAll('#checkbox_selector input[type="checkbox"]');
            checkboxes.forEach(checkbox => {
                checkbox.disabled = true;
            });
            return '';
        }
        """,
        Output(
            "dummy-output", "children"
        ),  # This is a dummy output since clientside_callback requires an output.
        Input("w1_radioSelect", "value"),
    )
    

    Image of a working example app

    Here is a full working example:

    from dash import Dash, dcc, html, Input, Output
    
    app = Dash(__name__)
    
    app.layout = html.Div(
        [
            html.H3("Radio Buttons"),
            dcc.RadioItems(
                id="w1_radioSelect",
                options=[
                    {"label": "Option 1", "value": "1"},
                    {"label": "Option 2", "value": "2"},
                    {"label": "Option 3", "value": "3"},
                ],
                value="1",
            ),
            html.H3("Check Boxes"),
            html.Div(
                id="checkbox_selector",
                children=[
                    dcc.Checklist(
                        id="checkbox1",
                        options=[{"label": "Checkbox 1", "value": "1"}],
                        value=[],
                    ),
                    dcc.Checklist(
                        id="checkbox2",
                        options=[{"label": "Checkbox 2", "value": "2"}],
                        value=[],
                    ),
                ],
            ),
            html.Div(id="dummy-output"),
            html.Button("Reset", id="reset", style={"margin-top": "20px"}),
        ]
    )
    
    # Disables all of the checkboxes
    app.clientside_callback(
        """
        function(value) {
            const checkboxes = document.querySelectorAll('#checkbox_selector input[type="checkbox"]');
            checkboxes.forEach(checkbox => {
                checkbox.disabled = true;
            });
            return '';
        }
        """,
        Output(
            "dummy-output", "children"
        ),  # This is a dummy output since clientside_callback requires an output.
        Input("w1_radioSelect", "value"),
    )
    
    # Enables all of the checkboxes
    app.clientside_callback(
        """
        function(value) {
            const checkboxes = document.querySelectorAll('#checkbox_selector input[type="checkbox"]');
            checkboxes.forEach(checkbox => {
                checkbox.disabled = false;
            });
            return {};
        }
        """,
        Output("dummy-output", "style"),
        Input("reset", "n_clicks"),
    )
    
    if __name__ == "__main__":
        app.run_server(debug=True)