Skip to content

Render interactive htmlwidget plots (e.g. canvasXpress) in plot_with_settings - #371

Open
neuhausi wants to merge 1 commit into
pharmaverse:mainfrom
neuhausi:canvasxpress-widget-render
Open

neuhausi wants to merge 1 commit into
pharmaverse:mainfrom
neuhausi:canvasxpress-widget-render

Conversation

@neuhausi

@neuhausi neuhausi commented Nov 5, 2026

Copy link
Copy Markdown

Summary

plot_with_settings currently renders only static R graphics (ggplot, trellis, grob, base). An htmlwidget returned by plot_r() falls through to the "other" type and never renders. This adds a render path for interactive htmlwidget objects (e.g. canvasXpress, plotly), as discussed in pharmaverse/teal#1757.

What changed

  • plot_with_settings_srv() gains a "widget" plot_type; htmlwidget plots render through the htmlwidgets shiny binding (shinyWidgetOutput / shinyRenderWidget) instead of renderPlot/plotOutput. The widget's class drives the correct JS output binding.
  • Height/width settings and full-screen apply as before; download produces a self-contained HTML file via htmlwidgets::saveWidget.
  • htmlwidgets added to Imports; canvasXpress added to Suggests (example + tests only).
  • Added an @examplesIf requireNamespace("canvasXpress") example on plot_with_settings, reusing the existing example structure.
  • Tests: plot_type detection for htmlwidget vs ggplot via shiny::testServer.

Design notes

  • Opt-in, no default change. Static-plot behaviour is untouched; the widget path triggers only when an app author returns an htmlwidget from plot_r. Existing callers (including teal.modules.clinical outputs) are unaffected — the interactive render is something a module opts into, e.g. routing tm_g_km / tm_g_forest_* through canvasXpress for the final render only.
  • The render path is generic to htmlwidget, so other widget packages benefit too.

Verification

  • shiny::testServer confirms plot_type() resolves to "widget" for a canvasXpress object and the UI emits the widget output binding.
  • Verified end-to-end in a running shiny app: a canvasXpress scatter renders inside the plot_with_settings card with the resize/download chrome and interactive behaviour.

Happy to adjust anything — naming, the example, or the download behaviour.

🤖 Generated with Claude Code

plot_with_settings_srv classified any non-ggplot/trellis/grob/base plot as
"other", so an htmlwidget (e.g. canvasXpress, plotly) returned by plot_r()
fell through and never rendered. Add a "widget" plot_type and route it
through the htmlwidgets shiny binding (shinyWidgetOutput / shinyRenderWidget)
instead of renderPlot/plotOutput. The widget's class drives the correct JS
output binding, height/width settings apply, and download produces a
self-contained HTML file (htmlwidgets::saveWidget). Static-plot behaviour is
unchanged.

- htmlwidgets added to Imports; canvasXpress added to Suggests (example/tests)
- @examplesIf requireNamespace("canvasXpress") example on plot_with_settings
- tests: plot_type detection for htmlwidget vs ggplot via shiny::testServer

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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

Successfully merging this pull request may close these issues.

1 participant