Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
def server(input, output, session):
@render.data_frame
def penguins_df():
return render.DataGrid(penguins, row_selection_mode="multiple") # <<
return render.DataGrid(penguins, selection_mode="rows") # <<

@render.ui()
@render.ui
def rows():
rows = input.penguins_df_selected_rows() # <<
rows = penguins_df.input_cell_selection()["rows"] # <<
selected = ", ".join(str(i) for i in sorted(rows)) if rows else "None"
return f"Rows selected: {selected}"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@

@render.ui()
def rows():
rows = input.penguins_df_selected_rows() # <<
rows = penguins_df.input_cell_selection()["rows"] # <<
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a good change in the sense of having the existing example run correctly with shiny 0.9.0.

We don't necessarily need to do it in this PR, but this example is less motivating now that the output object has more methods. It'd be nice if this example or a variant in this section gave more instruction about those methods and how to use them.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that there should be an example that shows other methods. I think it makes sense to merge now and then when @schloerke, discuss with him about other examples.

selected = ", ".join(str(i) for i in sorted(rows)) if rows else "None"
return f"Rows selected: {selected}"


@render.data_frame
def penguins_df():
return render.DataGrid(penguins, row_selection_mode="multiple") # <<
return render.DataGrid(penguins, selection_mode="rows") # <<
17 changes: 10 additions & 7 deletions components/outputs/data-grid/index.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,10 @@ listing:
dir: components/outputs/data-grid/
contents:
- title: Select Rows
description: Set `row_selection_mode` in `render.DataGrid()` to `"single"` to
allow the user to select one row at a time. Set it to `"multiple"` to allow
the user to select multiple rows at a time. Access the selection(s) as `input.<id>_selected_rows()`.
description: Set `selection_mode` in `render.DataGrid()` to `"row"` to
allow the user to select one row at a time. Set it to `"rows"` to allow
the user to select multiple rows at a time. Access the selection(s) as
`<id>.input_cell_selection()["rows"]`.
apps:
- title: Preview
file: app-variation-select-rows-core.py
Expand Down Expand Up @@ -126,13 +127,15 @@ To make a reactive Data Grid, follow three steps:

2. Within the server function, define a new function whose name matches the id used above. The function should assemble the table to display and then return the table wrapped in `render.DataGrid()`. Shiny will rerun this function whenever it needs to build or update the output that has the matching id.

3. Decorate the function with `@render.data_frame`
3. Decorate the function with `@render.data_frame`.

A Data Grid can also collect input from the user. To allow this, set `render.DataGrid(row_selection_mode="single")` or `render.DataGrid(row_selection_mode="multiple")` to allow the user to select one or more rows of the Data Grid.
A Data Grid can also collect input from the user. To allow this, set `render.DataGrid(selection_mode="row")` or `render.DataGrid(selection_mode="rows")` to allow the user to select one or more rows of the Data Grid.

The indices of the selected rows will be accessible within the server function as a reactive variable returned by `input.<id>_selected_rows()`, where <id> is the id of the `ui.output_data_frame()` associated with the table.
The indices of the selected rows will be accessible within the server function as a reactive variable returned by `<name>.input_cell_selection()["rows"]`, where <name> is the name of the function decorated with `@render.data_frame`.

The value returned will be `None` if no rows are selected, or a tuple of integers representing the indices of the selected rows. To filter a pandas data frame down to the selected rows, use `df.iloc[list(input.<id>_selected_rows())]`.
The value returned will be an empty tuple if no rows are selected, or a tuple of integers representing the indices of the selected rows. To filter a pandas data frame down to the selected rows, use `df.iloc[list(<name>.input_cell_selection()["rows"])]`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the very least, I think this section should give the user a hint that .input_cell_selection() isn't the only method (maybe in a paragraph below this one) with a pointer to our docs where they might learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea -- I've added a bit of info and link to the API docs.


For more information about interacting with data frames, see the API documentation for [Express](../../../api/express/express.render.data_frame.qmd) or [Core](../../../api/core/render.data_frame.qmd) syntax.

If your table is a data frame that uses the pandas styler, replace `ui.output_data_frame()` with `ui.output_table()` and `@render.data_frame` with `@render.table`.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
def server(input, output, session):
@render.data_frame
def penguins_df():
return render.DataTable(penguins, row_selection_mode="single") # <<
return render.DataTable(penguins, selection_mode="rows") # <<

@render.ui
def rows():
rows = input.penguins_df_selected_rows() # <<
rows = penguins_df.input_cell_selection()["rows"] # <<
selected = ", ".join(str(i) for i in sorted(rows)) if rows else "None"
return f"Rows selected: {selected}"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@

@render.ui
def rows():
rows = input.penguins_df_selected_rows() # <<
rows = penguins_df.input_cell_selection()["rows"] # <<
selected = ", ".join(str(i) for i in sorted(rows)) if rows else "None"
return f"Rows selected: {selected}"


@render.data_frame
def penguins_df():
return render.DataTable(penguins, row_selection_mode="single") # <<
return render.DataTable(penguins, selection_mode="rows") # <<
18 changes: 9 additions & 9 deletions components/outputs/datatable/index.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,10 @@ listing:
dir: components/outputs/datatable/
contents:
- title: Select Rows
description: Set `row_selection_mode` in `render.DataTable()` to `"single"` to
allow the user to select one row at a time. Set it to `"multiple"` to allow
the user to select multiple rows at a time. Access the selection(s) as `input.<id>_selected_rows()`.
description: Set `selection_mode` in `render.DataTable()` to `"row"` to
allow the user to select one row at a time. Set it to `"rows"` to allow
the user to select multiple rows at a time. Access the selection(s) as
`<id>.input_cell_selection()["rows"]`.
apps:
- title: Preview
file: app-variation-select-rows-core.py
Expand Down Expand Up @@ -126,16 +127,15 @@ To make a reactive Data Table, follow three steps:

2. Within the server function, define a new function whose name matches the id used above. The function should assemble the table to display and then return the table wrapped in `render.DataTable()`. Shiny will rerun this function whenever it needs to build or update the output that has the matching id.

3. Decorate the function with two decorators:
3. Decorate the function with `@render.data_frame`.

1. `@output`
2. `@render.data_frame`
A Data Table can also collect input from the user. To allow this, set `render.DataTable(selection_mode="row")` or `render.DataTable(selection_mode="rows")` to allow the user to select one or more rows of the Data Table.

A DataTable can also collect input from the user. To allow this, set `render.DataTable(row_selection_mode="single")` or `render.DataTable(row_selection_mode="multiple")` to allow the user to select one or more rows of the DataTable.
The indices of the selected rows will be accessible within the server function as a reactive variable returned by `<name>.input_cell_selection()["rows"]`, where <name> is the name of the function decorated with `@render.data_frame`.

The indices of the selected rows will be accessible within the server function as a reactive variable returned by `input.<id>_selected_rows()`, where <id> is the id of the `ui.output_data_frame()` associated with the table.
The value returned will be an empty tuple if no rows are selected, or a tuple of integers representing the indices of the selected rows. To filter a pandas data frame down to the selected rows, use `df.iloc[list(<name>.input_cell_selection()["rows"])]`.

The value returned will be `None` if no rows are selected, or a tuple of integers representing the indices of the selected rows. To filter a pandas data frame down to the selected rows, use `df.iloc[list(input.<id>_selected_rows())]`.
For more information about interacting with data frames, see the API documentation for [Express](../../../api/express/express.render.data_frame.qmd) or [Core](../../../api/core/render.data_frame.qmd) syntax.

If your table is a data frame that uses the pandas styler, replace `ui.output_data_frame()` with `ui.output_table()` and `@render.data_frame` with `@render.table`.

Expand Down
2 changes: 1 addition & 1 deletion py-shiny
Submodule py-shiny updated 56 files
+24 −0 CHANGELOG.md
+1 −1 Makefile
+6 −10 examples/dataframe/app.py
+1 −2 examples/moduleapp/app.py
+13 −19 scripts/htmlDependencies.R
+1 −1 shiny/__init__.py
+9 −9 shiny/_app.py
+3 −2 shiny/_typing_extensions.py
+1 −2 shiny/api-examples/Module/app-core.py
+10 −1 shiny/api-examples/data_frame_set_patches/app-core.py
+11 −1 shiny/api-examples/data_frame_set_patches/app-express.py
+63 −0 shiny/api-examples/theme/_purgecss.py
+28 −0 shiny/api-examples/theme/app-core-remote.py
+30 −0 shiny/api-examples/theme/app-core-shinyswatch.py
+32 −0 shiny/api-examples/theme/app-core.py
+25 −0 shiny/api-examples/theme/app-express-remote.py
+27 −0 shiny/api-examples/theme/app-express-shinyswatch.py
+27 −0 shiny/api-examples/theme/app-express.py
+8 −0 shiny/api-examples/theme/css/bootswatch-minty.min.css
+2 −0 shiny/experimental/ui/_deprecated.py
+2 −0 shiny/express/__init__.py
+0 −51 shiny/express/_mock_session.py
+36 −0 shiny/express/_module.py
+9 −9 shiny/express/_run.py
+160 −0 shiny/express/_stub_session.py
+15 −0 shiny/express/ui/_page.py
+5 −5 shiny/reactive/_reactives.py
+2 −18 shiny/render/_data_frame.py
+2 −1 shiny/render/_data_frame_utils/_datagridtable.py
+2 −2 shiny/render/_data_frame_utils/_selection.py
+4 −4 shiny/render/_render.py
+28 −10 shiny/render/renderer/_renderer.py
+1 −1 shiny/render/transformer/_transformer.py
+450 −261 shiny/session/_session.py
+1 −1 shiny/session/_utils.py
+1 −1 shiny/ui/_accordion.py
+38 −3 shiny/ui/_html_deps_external.py
+1 −1 shiny/ui/_input_update.py
+4 −2 shiny/ui/_modal.py
+1 −1 shiny/ui/_notification.py
+95 −4 shiny/ui/_page.py
+1 −1 shiny/ui/_progress.py
+1 −1 shiny/ui/_sidebar.py
+1 −1 shiny/www/shared/_version.json
+1 −1 shiny/www/shared/bootstrap/_version.json
+0 −2 shiny/www/shared/bootstrap/bootstrap.min.css
+2 −352 shiny/www/shared/ionrangeslider/css/ion.rangeSlider.css
+3 −3 shiny/www/shared/shiny.js
+2 −2 shiny/www/shared/shiny.js.map
+1 −1 shiny/www/shared/shiny.min.js
+2 −2 shiny/www/shared/shiny.min.js.map
+2 −0 tests/playwright/shiny/deprecated/output_transformer/test_output_transformer_example.py
+ tests/playwright/shiny/plot-sizing/bike.jpg
+2 −0 tests/playwright/shiny/server/output_transformer/test_output_transformer_async.py
+2 −23 tests/playwright/utils/deploy_utils.py
+10 −5 tests/pytest/test_modules.py