-
Notifications
You must be signed in to change notification settings - Fork 100
feat(data_frame): Add .update_data(data, *, reset)
and .update_cell_value(value, *, row, col)
#1449
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
Comments
I'm trying to edit the data in the data_frame, without re-render the data_frame output, so I can keep the filter/sort the user performed. Here is a test code, where when pressing the 'click' button, the second column of the second line should become 'xxx'. But it is not working I'm using the and the code
|
I've updated your app to use the new patches handler after being clicked. There were two subtle changes:
Final app (shinylive): from palmerpenguins import load_penguins
from shiny import App, reactive, render, ui
penguins = load_penguins()
app_ui = ui.page_fluid(
ui.h2("Palmer Penguins"),
ui.input_action_button("click", "click"),
ui.output_ui("rows"),
ui.output_data_frame("penguins_df"),
)
def server(input, output, session):
@render.data_frame
def penguins_df():
return render.DataTable(
penguins,
editable=True,
)
@reactive.Effect
@reactive.event(input.click)
def click():
print("click")
def edtx(*, patches) -> list[render.CellPatch]:
print("new!")
out = [
render.CellPatch(({"row_index": 1, "column_index": 1, "value": "xxx"}))
]
print(out)
return out
penguins_df.set_patches_fn(edtx)
# just testing if it works when editing another cell
@penguins_df.set_patches_fn
def edt(*, patches: list[render.CellPatch]) -> list[render.CellPatch]:
print("original")
out = [render.CellPatch(({"row_index": 1, "column_index": 1, "value": "e"}))]
return out
app = App(app_ui, server) I saw that the original cell location never escaped a saving state. This is being addressed in #1529 . |
It is definitely a possible feature! I have a sketch of what it could look like here: py-shiny/shiny/render/_data_frame.py Lines 719 to 739 in 6611277
It is currently not implemented as line 738 hints that we need a "send message to the browser" action that is not implemented in the typescript code. It would be similar to how we can update the sort from the server:
Note: This could also be something similar to
I do not believe a proxy object will be created within py-shiny. However, Python is pass by reference and we can empower our renderers to have extra methods. These extra methods, (e.g. One open question that I had was "how should the updates be supplied?". Should it be at the cell level or at the "whole data frame" level?
Thoughts? |
Thank you for your prompt reply. Here are a couple of examples of common use cases I can think of:
In the first case, editing at the cell level is the most efficient and streamlined approach. The second case requires a full table refresh, so resetting the entire data frame is quicker. (reactive on the @render.data_frame) But the user will lose the filters and sort. (even if the new options in 1.0 will help to reset them) Based on my experience, I would recommend prioritizing cell-level updates . Whole-table refreshes could be a second priority.
|
I fully agree, I think Python's by-reference approach is very useful and easy to code with. I intuitively built an App where the edit of a cell triggers other cells to change, just using the referenced data set (.data() and .data_view()). |
Currently, when a
I believe not losing these qualities are the root of the issue.
Pseudo code def update_data(self, data: DataFrameLikeT, *, reset: bool | None = None) -> None:
if reset is True:
# everything naturally resets
...
else:
action_type = warning if reset is None else error # error when reset = False
for each quality, display any error messages with the action_type
verify new data and old data have same column types
verify all existing edits and selections are within the bounds of the new data
Send message to browser with `data` and `reset` and for completeness def update_cell_value(self, value: TagNode, *, row: int, col: int) -> None:
Add cell patch info to internal cell patches dictionary
It feels off to call the currently set patches method on this submitted value
client_value = maybe_as_cell_html(value)
Send message to browser with `value: client_value`, `row`, and `col` |
I agree with your points. Your pseudo-code would be awesome. It would streamline the process (creation vs. editing vs. refresh data), keep it simple to code, and avoid getting lost in the @render reactivity (in R we need to use Isolate to avoid re-triggering the rendered) |
.update_data(data, *, reset)
and .update_cell_value(value, *, row, col)
I think my comment #1560 (comment) probably more applies to this discussion. This part:
, is also the problem I want to solve. My use case does not involve changing the data in any cells only controlling what the underlying dataframe in the datagrid component is compared to the original and how it is displayed.
Currently, my external state is (this is a sample):
So the use case is when choosing external state parameters and changing |
Using the example above of @render.data_frame
def penguins_df():
return render.DataTable(
penguins,
editable=True,
)
Correct. This would be available as
"Be able to construct the modified data frame". Hopefully this will be resolved with
This the @render.data_frame
def penguins_df_other():
return render.DataTable(penguins.data_view())
Example of using the modified data from the first data frame to display a second data frame:
|
Added Note: Support for |
@schloerke When is the 1.2 release planned? Or What is a good option to install the unreleased code? -->
perhaps? |
Uh oh!
There was an error while loading. Please reload this page.
In Shiny-R I often use the
dataTableProxy()
to manipulate the data shown in the DT, so the view is changed without reloading/regenerating the entire table.Is it possible to do it with the
data_frame
in Python?The text was updated successfully, but these errors were encountered: