How can I place text area, datatables and other interactive elements inside Accordion?

Hi @robertpfaff

To understand the error message, let’s take a look at one of your other Accordian items

dbc.AccordionItem(
    "This is the content of the second section",
    title="Item 2",
    item_id="acc_datatable",
),

This has three arguments, the first is a positional argument and the next two are keyword argument. (like regular Python functions) It’s a Dash convention that the first positional argument is the children property. So you could also write it this way:

dbc.AccordionItem(
    children = "This is the content of the second section",
    title="Item 2",
    item_id="acc_datatable",
),

Now if you want to add things to the AccorrdionItem Item you can make children a list:

dbc.AccordionItem(
    children = ["This is the content of the second section",  html.Div(id="MSG")],
    title="Item 2",
    item_id="acc_datatable",
),

But you also don’t need to include children= since it’s the first prop, so let’s turn it back into a positional argument:

dbc.AccordionItem(
     ["This is the content of the second section",  html.DIv(id="MSG")],
    title="Item 2",
    item_id="acc_datatable",
),

Like with any regular Python function, you got the error message because you tried to add other “children” elements as a positional argument after keyword arguments.

SyntaxError: positional argument follows keyword argument

For clarity, this will generate this error message: You have two positional arguments, and the second `html.Div(id=“MSG”) is after two keyword arguements.

dbc.AccordionItem(
    "This is the content of the second section", 
    title="Item 2",
    item_id="acc_datatable",
    html.DIv(id="MSG")
),

So, to put all the pieces together, here is the fix for the code you posted:
(Tip #1 try using a code formatter like black - it makes code easier to read and debug)

import dash
from dash import html, dcc, Input, Output, State
import dash_bootstrap_components as dbc


external_stylesheets = [dbc.themes.SUPERHERO]

app = dash.Dash(external_stylesheets=external_stylesheets)

app.layout = html.Div(
    [
        html.Br(),
        html.H5("Welcome to the Ingredible's Nutrition Assistant"),
        html.Br(),
        dbc.Accordion(
            [
                dbc.AccordionItem(
                    [
                        "This is the content of the first section",
                        html.Br(),
                        html.Br(),
                        html.Label("Please paste your recipe here."),
                        dcc.Textarea(
                            id="recipe-textarea",
                            value="",
                            style={"width": "80%", "height": 500},
                            placeholder="Please note: All information in brackets or parantheses will be deleted.",
                        ),
                        html.Br(),
                        html.Br(),
                        html.Button(
                            "Submit Recipe",
                            id="recipe-textarea-submit-button",
                            n_clicks=0,
                        ),
                        html.Br(),
                        html.Br(),
                        html.Div(id="MSG"),
                    ],
                    title="Step 1",
                    item_id="acc_textarea",
                ),
                dbc.AccordionItem(
                    "This is the content of the second section",
                    title="Item 2",
                    item_id="acc_datatable",
                ),
                dbc.AccordionItem(
                    "This is the content of the third section",
                    title="Item 3",
                    item_id="acc_report",
                ),
            ],
            id="accordion",
            active_item="acc_textarea",
        ),
        html.Div(id="accordion-contents", className="mt-3"),
    ]
)


@app.callback(
    Output("accordion-contents", "children"),
    [Input("accordion", "active_item")],
)
def change_item(item):
    return f"Item selected: {item}"


if __name__ == "__main__":
    app.run_server(debug=True, port=2000)

Tip #2, you can use the Bootstrap classes in the classNames prop for spacing, so you don’t need to use `html.Br() for that. Here’s a cheatsheet with all the Bootstrap classes that you might find helpful:https://dashcheatsheet.pythonanywhere.com/

So the final is:

from dash import Dash, html, dcc, Input, Output, State
import dash_bootstrap_components as dbc


external_stylesheets = [dbc.themes.SUPERHERO]

app = Dash(external_stylesheets=external_stylesheets)

app.layout = html.Div(
    [
        html.Br(),
        html.H5("Welcome to the Ingredible's Nutrition Assistant"),
        html.Br(),
        dbc.Accordion(
            [
                dbc.AccordionItem(
                    [
                        html.Div("This is the content of the first section", className="mb-4"),
                        html.Label("Please paste your recipe here."),
                        dcc.Textarea(
                            id="recipe-textarea",
                            value="",
                            style={"width": "80%", "height": 500},
                            placeholder="Please note: All information in brackets or parantheses will be deleted.",
                            className="mb-4"
                        ),
                        html.Button(
                            "Submit Recipe",
                            id="recipe-textarea-submit-button",
                            n_clicks=0,
                            className="mb-4"
                        ),
                        html.Div(id="MSG"),
                    ],
                    title="Step 1",
                    item_id="acc_textarea",
                ),
                dbc.AccordionItem(
                    "This is the content of the second section",
                    title="Item 2",
                    item_id="acc_datatable",
                ),
                dbc.AccordionItem(
                    "This is the content of the third section",
                    title="Item 3",
                    item_id="acc_report",
                ),
            ],
            id="accordion",
            active_item="acc_textarea",
        ),
        html.Div(id="accordion-contents", className="mt-3"),
    ]
)


@app.callback(
    Output("accordion-contents", "children"),
    [Input("accordion", "active_item")],
)
def change_item(item):
    return f"Item selected: {item}"


if __name__ == "__main__":
    app.run_server(debug=True, port=2000)

2 Likes