# Is it possible to assign a callback to a button generated by a function call?

**URL:** <https://community.plotly.com/t/is-it-possible-to-assign-a-callback-to-a-button-generated-by-a-function-call/18940>\
**Category:** Dash Python\
**Created:** [February 2, 2019, 1:25pm UTC](https://community.plotly.com/t/is-it-possible-to-assign-a-callback-to-a-button-generated-by-a-function-call/18940 "2019-02-02T13:25:11Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![clstaudt](https://avatars.discourse-cdn.com/v4/letter/c/53a042/32.png) [@clstaudt](https://community.plotly.com/u/clstaudt)\
**Post date:** [February 2, 2019, 1:25pm UTC](https://community.plotly.com/t/is-it-possible-to-assign-a-callback-to-a-button-generated-by-a-function-call/18940/1 "2019-02-02T13:25:11Z")

</div>

Code redundancy is the root of all evil in software development, so I try to not repeat myself and write a function for frequently used UI components of my Dash app. Take a look at this search field and button:

```
def search_field(field_id, button_id, label, placeholder=""):
    field = html.Div(
        className="field has-addons",
        children=[
            html.Label(label, className="label")
            html.Div(
                dcc.Input(
                    id=field_id,
                    className="input",
                    type="text",
                    placeholder=placeholder
                ),
                className="control"
            ),
            html.Div(
                html.Button(
                    html.I(className="fas fa-search"),
                    id=button_id,
                    className="button"
                ),
                className="control"
            )
        ]
    )
    return field

```

I use a function call to insert such a button into my layout:

```
elements.search_field(
    field_id="search-term-field",
    button_id="search-button",
    label="Beschreibungen durchsuchen",
    placeholder="Suchbegriff"
)

```

So far so good:

![52](https://us1.discourse-cdn.com/flex024/uploads/plot/original/2X/a/a18424f66bbbb91f2a892c1f0de7567edcdcaf80.png)

However, assigning a callback to the button does not seem to work:

```
@app.callback(
    Output('search-result-area', 'children'),
    [
        Input('search-button', 'n_clicks')
    ],
    [
        State('search-term-field', 'value')
    ]
)
def update_search_result(n_clicks, search_term):
    ...

```

Is this something that Dash does not support?

---

<div class="post-metadata">

**Author:** ![Emil](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/emil/32/31734_2.png) [@Emil](https://community.plotly.com/u/Emil)\
**Post date:** [February 2, 2019, 4:52pm UTC](https://community.plotly.com/t/is-it-possible-to-assign-a-callback-to-a-button-generated-by-a-function-call/18940/2 "2019-02-02T16:52:53Z")

</div>

Is the button generated before or after the app is started?

---

<div class="post-metadata">

**Author:** ![clstaudt](https://avatars.discourse-cdn.com/v4/letter/c/53a042/32.png) [@clstaudt](https://community.plotly.com/u/clstaudt)\
**Post date:** [February 2, 2019, 5:05pm UTC](https://community.plotly.com/t/is-it-possible-to-assign-a-callback-to-a-button-generated-by-a-function-call/18940/3 "2019-02-02T17:05:33Z")

</div>

The function call that generates it happens before the app is started.

---

<div class="post-metadata">

**Author:** ![nedned](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/nedned/32/8795_2.png) [@nedned](https://community.plotly.com/u/nedned)\
**Post date:** [February 3, 2019, 1:18am UTC](https://community.plotly.com/t/is-it-possible-to-assign-a-callback-to-a-button-generated-by-a-function-call/18940/4 "2019-02-03T01:18:44Z")

</div>

All your callbacks need to be registered before the app starts, which it sounds like you’re doing. The issue is probably that you’re modifying the DOM directly. This generally doesn’t play well with React, which has it’s own virtual DOM, and there’s also a bunch of logic that the Dash renderer does to keep track of modifications to the layout, which won’t be triggered via direct access.

In general, I think you need to restrict layout changes to being performed by Dash callbacks.

---

<div class="post-metadata">

**Author:** ![clstaudt](https://avatars.discourse-cdn.com/v4/letter/c/53a042/32.png) [@clstaudt](https://community.plotly.com/u/clstaudt)\
**Post date:** [February 3, 2019, 10:05am UTC](https://community.plotly.com/t/is-it-possible-to-assign-a-callback-to-a-button-generated-by-a-function-call/18940/5 "2019-02-03T10:05:01Z")

</div>

I’d like to understand better what you mean by “modifying the DOM directly”.

> In general, I think you need to restrict layout changes to being performed by Dash callbacks.

I’m also not sure that I understand this correctly. I would say the layout changes are ultimately all performed by callbacks. I use function calls to make the code that constructs the layout less verbose and redundant. From a Python point of view, this code should be equivalent.

---

<div class="post-metadata">

**Author:** ![Emil](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/emil/32/31734_2.png) [@Emil](https://community.plotly.com/u/Emil)\
**Post date:** [February 3, 2019, 4:19pm UTC](https://community.plotly.com/t/is-it-possible-to-assign-a-callback-to-a-button-generated-by-a-function-call/18940/6 "2019-02-03T16:19:21Z")

</div>

If the callbacks are attached prior to starting the app, I see no reason that it should not work. Can you post a MWE?

---

<div class="post-metadata">

**Author:** ![nedned](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/nedned/32/8795_2.png) [@nedned](https://community.plotly.com/u/nedned)\
**Post date:** [February 4, 2019, 2:03am UTC](https://community.plotly.com/t/is-it-possible-to-assign-a-callback-to-a-button-generated-by-a-function-call/18940/7 "2019-02-04T02:03:42Z")

</div>

Oh right, sorry. I thought that second snippet was JavaScript for some reason, so I guess ignore my comments about modifying the DOM directly.

It sounds like what you’re trying to do should work. Echoing @Emil, can you post a minimal working example that shows this issue?

---

<div class="post-metadata">

**Author:** ![clstaudt](https://avatars.discourse-cdn.com/v4/letter/c/53a042/32.png) [@clstaudt](https://community.plotly.com/u/clstaudt)\
**Post date:** [February 4, 2019, 4:44pm UTC](https://community.plotly.com/t/is-it-possible-to-assign-a-callback-to-a-button-generated-by-a-function-call/18940/8 "2019-02-04T16:44:34Z")

</div>

Here is a fairly minimal example that is not working as intended. I am trying to show a new box in a previously empty area on the click of a button. The button is generated via a function call.

(I think `components.text_field` illustrates why it is necessary to wrap frequently used parts of the layout into a function: Typing this out for every field of a form would quickly amount to unreadable code)

When clicked, the button just doesn’t do anything, and there is no error message.

Content of `main.py`:

```
import flask

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State

import components

# linked resources
## stylesheets
stylesheets = [
    "https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.min.css", # Bulma
]

# app
## flask server
server = flask.Flask( __name__ )

## create app
app = dash.Dash(
    __name__ ,
    server=server,
    external_stylesheets=stylesheets
)

# layout

## navigation
navbar = html.Nav(
    className="navbar",
    children=[
        html.Div(
            className="navbar-brand",
            children=[
                html.Div(
                    className="navbar-item",
                    children=[
                    ]
                )
            ]
        ),
        html.Div(
            className="navbar-menu is-active",
            children=[
                html.Div(
                    className="navbar-start",
                    children=[]
                )
            ]
        ),
        html.Div(
            className="navbar-end",
            children=[
                dcc.Link("Support", className="navbar-item"),
            ]
        )
    ]
)

## boxes
sim_param_box = html.Div(
    id="sim-param-area",
    className="box",
    children=[
        components.text_field(
            field_id="start-time-field",
            label="Start",
            placeholder="YYYY/MM/DD hh:mm"
        ),
        components.text_field(
            field_id="stop-field",
            label="Stop",
            placeholder="YYYY/MM/DD hh:mm"
        ),
        components.text_field(
            field_id="tick-field",
            label="1 Tick =",
            placeholder="[s]"
        ),
        components.enter_button(
            button_id="sim-param-enter-button",
            text=None,
            tooltip="Simulation initialisieren"
        )
    ]
)

sim_param_area = html.Div(
    children=sim_param_box,
    className="section",
)

sim_results_box = html.Div(
    id="sim-results-box",
    className="box",
    children=[
        "Test"
    ]
)

sim_results_area = html.Div(
    id="sim-results-area",
    className="section",
    children=[],
)

## main layout

main_area = html.Div(
    className="content",
    id="main-area",
    children=[
        sim_param_area,
        sim_results_area
    ]
)

app.layout = html.Div(
    className="container",
    children=[
        navbar,
        main_area
    ]
)

# callbacks

@app.callback(
    Output("sim-results-area", "children"),
    [
        Input("sim-param-enter-button", "n_clicks")
    ]
)
def enter_sim_params(n_clicks):
    if n_clicks:
        return sim_results_box

if __name__ == ' __main__':
    app.run_server(debug=True)

```

Content of `components.py`:

```
import dash
import dash_core_components as dcc
import dash_html_components as html

def text_field(field_id, label=None, placeholder=None):

    field = html.Div(
        children=[
            html.Label(label, className="label"),
            html.Div(
                dcc.Input(
                    className="input",
                    type="text",
                    placeholder=placeholder,
                ),
                id=field_id,
                className="control"
            )
        ],
        className="field",
    )
    return field

def enter_button(button_id, text=None, tooltip=""):
    button_label = html.I("⏎")
    if text:
        button_label = text
    return html.Button(
        id=button_id,
        title=tooltip,
        className="button is-large is-primary is-outlined",
        style={"width": "250px"},
        children=[
            button_label
        ]
    )
```

---

<div class="post-metadata">

**Author:** ![nedned](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/nedned/32/8795_2.png) [@nedned](https://community.plotly.com/u/nedned)\
**Post date:** [February 7, 2019, 12:11pm UTC](https://community.plotly.com/t/is-it-possible-to-assign-a-callback-to-a-button-generated-by-a-function-call/18940/9 "2019-02-07T12:11:47Z")

</div>

Sorry for the slow reply. Just tried out your example, but I’m not sure I can see the issue you’re describing. When I click the enter button with the arrow on it, a box with “Test” in it is created successfully. Is that the behaviour you’re saying is not happening?

Perhaps try updating you all your Dash libraries to the latest versions.

Oh, and the answer to your question is yep, you can definitely use functions to wrap up and abstract away layout creation. It’s a great way to make your apps more reusabale and reusable.

---

<div class="post-metadata">

**Author:** ![clstaudt](https://avatars.discourse-cdn.com/v4/letter/c/53a042/32.png) [@clstaudt](https://community.plotly.com/u/clstaudt)\
**Post date:** [February 12, 2019, 1:43pm UTC](https://community.plotly.com/t/is-it-possible-to-assign-a-callback-to-a-button-generated-by-a-function-call/18940/10 "2019-02-12T13:43:54Z")

</div>

Thanks for confirming that it works for you. Will check whether the issue has disappeared after a restart, as has been the case before.

It seems that one thing that makes Dash apps very difficult to debug when you generate components with function calls is that you need to suppress exceptions:

`app.config['suppress_callback_exceptions'] = True`

In effect, some things just don’t work and you don’t get error messages. Trial and error debugging follows. Could this be improved?

---

<div class="post-metadata">

**Author:** ![nedned](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/nedned/32/8795_2.png) [@nedned](https://community.plotly.com/u/nedned)\
**Post date:** [February 21, 2019, 7:55am UTC](https://community.plotly.com/t/is-it-possible-to-assign-a-callback-to-a-button-generated-by-a-function-call/18940/11 "2019-02-21T07:55:44Z")

</div>

It is actually possible to retain callback validation, however you have to do some work. See the section “Dynamically Create a Layout for Multi-Page App Validation” in the [Multi Apps page](https://dash.plot.ly/urls) of the Dash docs and the code snippet following.

You essentially need to create a layout function that checks whether Dash is returning the layout for a request, or just for validation. If for validation, then the function you make needs to return every possible layout component all concatenated together, and you’ll get them validated.

The catch is that you can’t combine callbacks and layouts within the different modules for each page when doing this. See this issue: [https://github.com/plotly/dash/issues/519](https://github.com/plotly/dash/issues/519)
