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

Modal reopens when render.DataGrid.data_view upstream data changes but there is no selection #1368

Open
SamEdwardes opened this issue May 9, 2024 · 0 comments

Comments

@SamEdwardes
Copy link

SamEdwardes commented May 9, 2024

Description

I have a modal that opens when a user clicks on a row from render.DataGrid. This works great! However, when the "upstream" data changes and the resulting data in render.DataGrid changes, the modal opens again.

The expected behaviour would be that the modal should not re-open, as no value is selected.

I could be missing something about the correct way to implement this. But I cannot figure it out!

Recording

The unexpected behaviour happens at the 9 second mark.

Screenshot.2024-05-09.at.15.41.30.mp4

Reprex

shiny==0.9.0
anyio==4.3.0
appdirs==1.4.4
asgiref==3.8.1
click==8.1.7
h11==0.14.0
htmltools==0.5.1
idna==3.7
linkify-it-py==2.0.3
markdown-it-py==3.0.0
mdit-py-plugins==0.4.0
mdurl==0.1.2
numpy==1.26.4
packaging==24.0
pandas==2.2.2
prompt-toolkit==3.0.36
python-dateutil==2.9.0.post0
python-multipart==0.0.9
pytz==2024.1
questionary==2.0.1
shiny==0.9.0
six==1.16.0
sniffio==1.3.1
starlette==0.37.2
typing-extensions==4.11.0
tzdata==2024.1
uc-micro-py==1.0.3
uvicorn==0.29.0
watchfiles==0.21.0
wcwidth==0.2.13
websockets==12.0
import pandas as pd
import numpy as np
from shiny import App, reactive, render, req, ui


categories = ["Category1", "Category2", "Category3", "Category4", "Category5"]

df = pd.DataFrame({
    "category": pd.Categorical(categories * 4),
    "number": np.random.rand(20),
})


app_ui = ui.page_fillable(
    ui.input_select("category", "Select a category", categories),
    ui.card(ui.output_data_frame("data")),
)


def server(input, output, session):

    @render.data_frame
    def data():
        selected_category = input.category()
        return render.DataGrid(
            df.loc[df["category"] == selected_category, :],
            selection_mode="row"
        )

    @reactive.effect
    def show_modal():
        data_selected = data.data_view(selected=True)
        req(not data_selected.empty)
        print(data_selected)
        modal = ui.modal(
            ui.tags.code(data_selected.to_json(orient="records"))
        )
        ui.modal_show(modal)



app = App(app_ui, server)

Possible solutions

Use .update_cell_selection(None)

This still results in the same behaviour.

Also, it is correct that data_table.update_cell_selection(None) needs to be run in an async function?

import pandas as pd
import numpy as np
from shiny import App, reactive, render, req, ui


categories = ["Category1", "Category2", "Category3", "Category4", "Category5"]

df = pd.DataFrame({
    "category": pd.Categorical(categories * 4),
    "number": np.random.rand(20),
})


app_ui = ui.page_fillable(
    ui.input_select("category", "Select a category", categories),
    ui.card(ui.output_data_frame("data_table")),
)


def server(input, output, session):

    @reactive.calc
    def filter_data() -> pd.DataFrame:
        print("Data updating ------------------------------------------")
        selected_category = input.category()
        return df.loc[df["category"] == selected_category, :]


    @render.data_frame
    def data_table():
        print("Updating table output.")
        return render.DataGrid(filter_data(), selection_mode="row")

    # Why does `data_table.update_cell_selection` need to be async?
    @reactive.effect(priority=99)
    @reactive.event(filter_data)
    async def clear_selection():
        print("Clearing selection")
        await data_table.update_cell_selection(None)

    @reactive.effect
    @reactive.event(data_table.input_cell_selection, ignore_init=True, ignore_none=True)
    def show_modal():
        print("Deciding to show modal...")
        data_selected = data_table.data_view(selected=True)
        print(data_selected.to_json(orient="records"))
        req(not data_selected.empty)
        print("Showing modal")
        modal = ui.modal(ui.tags.code(data_selected.to_json(orient="records")))
        ui.modal_show(modal)


app = App(app_ui, server)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant