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

Implement shiny integrations #16

Open
machow opened this issue Aug 29, 2024 · 5 comments
Open

Implement shiny integrations #16

machow opened this issue Aug 29, 2024 · 5 comments
Assignees

Comments

@machow
Copy link
Owner

machow commented Aug 29, 2024

reactable for R has shiny integrations that let you update a table output reactively. We should be able to wire into py-shiny to do something similar. This might me we provide render, update, and output functions for use with shiny.

https://glin.github.io/reactable/reference/updateReactable.html

See also these issues related to how the widget is wired (which might help as we dig into the widget internals):

@machow
Copy link
Owner Author

machow commented Sep 10, 2024

This is being evaluated as part of posit-dev/py-shiny#1639

@machow
Copy link
Owner Author

machow commented Sep 12, 2024

from chatting w/ @schloerke RE this py-shiny reactable exploration spike, evaluating:

1.  Wire up basic reactivity (simple)
2. Make reactable-py editable (complex)
  * research: what would it take to make reactable.js editable?
  * would involve submitting a PR to glin/reactable
3. Auto data types -> reactable column

It sounds like...

  • simple thing (wire up basic reactivity): would be fairly quick and worthwhile.
  • complex thing (make editable): would take a lot of effort, would be a down the road thing

@thohan88
Copy link

Great to see this being ported to python! Should reactable-py work with shiny in the current version?

I attempted:

from shiny import App, reactive, render, req, ui
from shinywidgets import render_widget, output_widget

app_ui = ui.page_fluid(
    output_widget("tbl"),
)

def server(input, output, session):
    @output
    @render_widget
    def tbl():
        from reactable.data import cars_93
        from reactable.models import Reactable
        react = Reactable(data=cars_93)
        return react.to_widget()
        
app = App(app_ui, server)

This returns:
image

INFO:     Uvicorn running on http://127.0.0.1:1410 (Press CTRL+C to quit)
INFO:     Started reloader process [19884] using WatchFiles
INFO:     Started server process [19886]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     127.0.0.1:62092 - "GET / HTTP/1.1" 200 OK
INFO:     ('127.0.0.1', 62097) - "WebSocket /websocket/" [accepted]
INFO:     connection open
INFO:     127.0.0.1:62092 - "GET /%40widgetti/jupyter-react.js HTTP/1.1" 404 Not Found

I could not find the reference to @widgetti/jupyter-react.js anywhere.

@machow
Copy link
Owner Author

machow commented Sep 20, 2024

I've explored a bit, and with some tweaking was able to get the js loaded, but wasn't able to get the widget to render. I noticed that simple ipyreact Widgets also don't render, so opened an issue on py-shinywidgets:

posit-dev/py-shinywidgets#160

@machow
Copy link
Owner Author

machow commented Oct 3, 2024

Alright, here's a minimal example of getting it to work right now. The trick is defining a reactive calc that loads the dependencies reactable-py needs (this normally happens automatically in jupyter):

from shiny.express import ui
from shiny import reactive
from reactable import Reactable
from reactable.data import cars_93
from shinywidgets import render_widget
import ipyreact

from pathlib import Path
from importlib_resources import files

STATIC_FILES = files("reactable.static")

ui.include_css(Path(STATIC_FILES / "reactable-py.esm.css"))


# Reactive calc: define the reactable Module -----


@reactive.calc
def dependency():
    # Module needs to be created here, because shiny won't run the on construction hook, until the
    # shiny app is running, and that is after all the code is initially run...
    mod = ipyreact.define_module("reactable", Path(str(STATIC_FILES / "reactable-py.esm.js")))
    return mod


# Uses the calc before rendering, to ensure the Module is loaded ----


@render_widget
def out():
    dependency()          # <----- note the dependency reactive calc call
    return Reactable(cars_93).to_widget()

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

No branches or pull requests

3 participants