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

"raise PreventUpdate" prevents any side channel property updates through "set_props" #2958

Open
JNeiger opened this issue Aug 22, 2024 · 0 comments
Labels
bug something broken P3 not needed for current cycle

Comments

@JNeiger
Copy link

JNeiger commented Aug 22, 2024

Thanks for maintaining this library, I really appreciate it!

Describe your context

dash                              2.17.0
dash-core-components              2.0.0
dash-extensions                   1.0.15
dash-html-components              2.0.0
dash-table                        5.0.0

Describe the bug

When set_props is used within a callback that later hits raise PreventUpdate, the properties set by set_props do not propagate back to the server when the callback ends. This is in direct contrast to no_update. Based on my understanding of the docs here, both raise PreventUpdate and return no_update (if applied to all outputs) should both have the same behavior in regards to updating outputs.

@callback(...)
def callback_prevent_update(...):
  """Does NOT set prop_id_here->is_open to True"""
  set_props("prop_id_here", {"is_open": True})
  raise PreventUpdate

@callback(...)
def callback_no_update(...):
  """Does set prop_id_here->is_open to True"""
  set_props("prop_id_here", {"is_open": True})
  return no_update

Expected behavior

I expected that raise PreventUpdate would have the exact same behavior as return no_update (when applied to all outputs) which is that the outputs of a callback do not update, but the set_props call still goes through.

If it's expected that these produce two different behaviors, then it might be worth updating the caveats here with this case as it's unexpected behavior compared to the standard Input/Output behavior in callbacks. I'm happy to help update the documentation if there's a code pointer on where to add it! ( I didn't see the docs folder on a quick initial look)

Screenshots
In the chrome networking tab, the original callback in the example returns the following:
image

When raise PreventUpdate is added, the example returns the following (Note the status code in the second image is now 204 instead of 200):
image
image

Minimal Reproducible Example
This is taken directly from here, with the only change being the raise PreventUpdate line

Steps to reproduce

  1. Load the page
  2. Click on one of the rows
  3. A modal should have popped up, but does not due to the raise PreventUpdate
import dash_ag_grid as dag
from dash import Dash, Input, html, ctx, callback, set_props
from dash.exceptions import PreventUpdate
import dash_bootstrap_components as dbc

app = Dash(__name__, external_stylesheets=[dbc.themes.SPACELAB])

rowData = [
    {"make": "Toyota", "model": "Celica", "price": 35000},
    {"make": "Ford", "model": "Mondeo", "price": 32000},
    {"make": "Porsche", "model": "Boxster", "price": 72000},
]

app.layout = html.Div(
    [
        dag.AgGrid(
            id="setprops-row-selection-popup",
            rowData=rowData,
            columnDefs=[{"field": i} for i in ["make", "model", "price"]],
            columnSize="sizeToFit",
            dashGridOptions={"rowSelection": "single", "animateRows": False},
        ),
        dbc.Modal(
            [
                dbc.ModalHeader("More information about selected row"),
                dbc.ModalBody(id="setprops-row-selection-modal-content"),
                dbc.ModalFooter(dbc.Button("Close", id="setprops-row-selection-modal-close", className="ml-auto")),
            ],
            id="setprops-row-selection-modal",
        ),
    ]
)

@callback(
    Input("setprops-row-selection-popup", "selectedRows"),
    Input("setprops-row-selection-modal-close", "n_clicks"),
    prevent_initial_call=True,
)
def open_modal(selection, _):
    if ctx.triggered_id == "setprops-row-selection-modal-close":
        # Close the modal
        set_props("setprops-row-selection-modal", {'is_open': False})
    elif ctx.triggered_id == "setprops-row-selection-popup" and selection:
        # Open the modal and display the selected row content
        content_to_display = "You selected " + ", ".join(
            [
                f"{s['make']} (model {s['model']} and price {s['price']})"
                for s in selection
            ]
        )
        set_props("setprops-row-selection-modal", {'is_open': True})
        set_props("setprops-row-selection-modal-content", {'children': content_to_display})

    raise PreventUpdate

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=8050, debug=True)
@gvwilson gvwilson changed the title [BUG] "raise PreventUpdate" prevents any side channel property updates through "set_props" "raise PreventUpdate" prevents any side channel property updates through "set_props" Aug 26, 2024
@gvwilson gvwilson added bug something broken P3 not needed for current cycle labels Aug 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug something broken P3 not needed for current cycle
Projects
None yet
Development

No branches or pull requests

2 participants