jsonbourne
jsonbourne

Reputation: 973

How to add separate Html elements on a button click on Python Dash

A very trivial scenario I am trying to achieve using Python dash. Adding similar elements on each button click one after another.

Below is the code.

app.layout = {
  html.Button(id='add-element-button', n_clicks=0, children='Add Input Element'),
  html.Div(id="layout")
}

@app.callback(Output('layout', 'children'),
              [Input('add-element-button', 'n_clicks')])
def add_strategy_divison(val):
    if val:
        return html.Div(id=f"heading_element_{val}",
            [
                html.H1(id=f"heading_{val}", children=f"{val} Heading"),
            ]
            )
    else:
        raise PreventUpdate

What seems to be happening is instead of adding new elements, it just overwrites the first heading element (which is successfully created on first click) with the new one along with the new id.

Does anyone have any idea what could be happening? Thanks!

Upvotes: 3

Views: 4022

Answers (1)

MrLeeh
MrLeeh

Reputation: 5589

The behaviour you described makes perfect sense. You return an new div-element which means you overwrite the children attribute of the layout element. This way you will always replace existing children.

For this to work the way you want it you need to get the current children of your layout element and add your new element to it. Pass the current children as a State object to your callback. Now append your element to children an return the list.

@app.callback(
    Output('layout', 'children'),
    [Input('add-element-button', 'n_clicks')],
    [State('layout', 'children')],
)
def add_strategy_divison(val, children):
    if val:
        el = html.Div(id=f"heading_element_{val}", [
            html.H1(id=f"heading_{val}", children=f"{val} Heading"),
        ])
        children.append(el)
        return children
    else:
        raise PreventUpdate

Upvotes: 4

Related Questions