Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Returning dbc.Button in a list of children triggers an erroneous n_click event #1047

Open
matt-sd-watson opened this issue Jul 30, 2024 · 3 comments

Comments

@matt-sd-watson
Copy link

Before opening:

Please fill out the below information as much as possible.

  • dash version: 2.10.2
  • dash-bootstrap-components version: 1.4.1
  • components affected by bug: dbc.Button

What is happening?

My application accesses a list of div children in a callback, where the children each comprise of a dbc.Col that itself contains a dbc.Button for selecting the object in the column. These columns form image tiles that can be selected by the user based on an index pattern.

If the children are accessed through a callback, modified, and then returned, the first dbc.Button found in the list of children is clicked automatically.

What should be happening?

One would expect that the children are returned with no n_click event taking place.

Code

Here is some basic code demonstrating how the children are initially set up:

row_children = []
# here, itertate over a list of images with corresponding labels
for key, value in images.items():
           row_children.append(dbc.Col(dbc.Card([dbc.CardBody([html.B(label, className="card-text", id=key),
                                                                dbc.Button(children=html.Span(
                                                                    [html.I(className="fa-solid fa-plus-circle",
                                                                            style={"display": "inline-block",
                                                                                   "margin-right": "7.5px",
                                                                                   "margin-top": "-5px"})],
                                                                    style={"display": "flex", "float": "center",
                                                                           "justifyContent": "center"}),
                                                                    id={'type': 'gallery-channel',
                                                                        'index': key},
                                                                    outline=False, color="light",
                                                                    className="me-1", size="m",
                                                                    style={"padding": "5px",
                                                                           "margin-left": "10px",
                                                                           "margin-top": "2.5px"}),
                                                                dbc.Tooltip(f'Add {label} to canvas',
                                                                            target={'type': 'gallery-channel',
                                                                                    'index': key}),
                                                                ]),
                                                  dbc.CardImg(src=Image.fromarray(image_render).convert('RGB'),
                                                              bottom=True)]), width=3))
return row_children

This produces rows of image thumbnails that are selectable by clicking the plus buttons, like this:

Screenshot from 2024-07-30 09-08-14

In a callback, the children are accessed, modified, and then returned. In the example below, the children are parsed recursively, and the image labels are changed based on a dictionary of names, without modifying the underlying images:

@dash_app.callback(Output('image-gallery-row', 'children'),
                       Input('alias-dict', 'data'),
                       State('image-gallery-row', 'children'),
                       prevent_initial_call=True)
    def create_channel_tile_gallery_grid(aliases, current_children):
            return recursively_parse_thumbnail_children(current_children aliases)

producing:

Screenshot from 2024-07-30 09-09-50

However, when this callback finishes, it always triggers the first button corresponding to the first thumbnail to be clicked erroneously. In this case, it would automatically click the button corresponding to Fibronectin, even though the user made no such click.

@AnnMarieW
Copy link
Contributor

Hi @matt-sd-watson

This may be a Dash issue, rather than dash-bootstrap-components. To test my theory, could you please replace the dbc.Button with and html.Button ? I expect that you will get the same results.

If it's a Dash issue, please open a topic in the Dash Community Forum. It's not uncommon for a callback to trigger when adding components dynamically from a callback. When you post, it's helpful to include a complete minimal example that can be run to reproduce the issue.

@matt-sd-watson
Copy link
Author

Switching to html.Button appears to have the problem occur less frequently. It doesn't appear deterministic at this point.
I am also seeing if explicitly setting n_clicks=0 for each button helps.
Unfortunately the complexity and size of the app codebase, as well as the licence, prevents me from sharing more code that above.

@AnnMarieW
Copy link
Contributor

Without a minimal example, it's going to be difficult to help in any meaningful way. It should be possible to make something without including any proprietary information.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants