From 7fbb4867bd0b23871b6fcaa942afbb832f9a3609 Mon Sep 17 00:00:00 2001 From: Carson Date: Fri, 30 Aug 2019 13:12:07 -0500 Subject: [PATCH 1/2] Revert "Revert "Merge pull request #1539 from ropensci/renderWidgetPrep"" This reverts commit 285673153adc56ec0cbb8a01d0af4c46f3894b00. --- R/shiny.R | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/R/shiny.R b/R/shiny.R index d46f164c9b..0bb4bf38b1 100644 --- a/R/shiny.R +++ b/R/shiny.R @@ -37,11 +37,21 @@ plotlyOutput <- function(outputId, width = "100%", height = "400px", #' @rdname plotly-shiny #' @export renderPlotly <- function(expr, env = parent.frame(), quoted = FALSE) { - if (!quoted) { expr <- substitute(expr) } # force quoted - # this makes it possible to pass a ggplot2 object to renderPlotly() - # https://github.com/ramnathv/htmlwidgets/issues/166#issuecomment-153000306 - expr <- as.call(list(call(":::", quote("plotly"), quote("prepareWidget")), expr)) - renderFunc <- shinyRenderWidget(expr, plotlyOutput, env, quoted = TRUE) + if (!quoted) { + quoted <- TRUE + expr <- substitute(expr) + } + # Install the (user-supplied) expression as a function + # This way, if the user-supplied expression contains a return() + # statement, we can capture that return value and pass it along + # to prepareWidget() + # prepareWidget() makes it possible to pass different non-plotly + # objects to renderPlotly() (e.g., ggplot2, promises). It also is used + # to inform event_data about what events have been registered + shiny::installExprFunction(expr, "func", env, quoted) + renderFunc <- shinyRenderWidget( + plotly:::prepareWidget(func()), plotlyOutput, env, quoted + ) # remove 'internal' plotly attributes that are known to cause false # positive test results in shinytest (snapshotPreprocessOutput was added # in shiny 1.0.3.9002, but we require >= 1.1) @@ -57,13 +67,14 @@ renderPlotly <- function(expr, env = parent.frame(), quoted = FALSE) { # Converts a plot, OR a promise of a plot, to plotly prepareWidget <- function(x) { - p <- if (promises::is.promising(x)) { - promises::then(x, ggplotly) + if (promises::is.promising(x)) { + promises::then( + promises::then(x, ggplotly), + register_plot_events + ) } else { - ggplotly(x) + register_plot_events(ggplotly(x)) } - register_plot_events(p) - p } register_plot_events <- function(p) { @@ -73,6 +84,7 @@ register_plot_events <- function(p) { session$userData$plotlyShinyEventIDs, eventIDs )) + p } From 1a714b83b3710cf94e840835052e108df259cb4d Mon Sep 17 00:00:00 2001 From: Carson Date: Fri, 30 Aug 2019 13:13:41 -0500 Subject: [PATCH 2/2] pass along a quoted expr that calls func() --- R/shiny.R | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/R/shiny.R b/R/shiny.R index 0bb4bf38b1..bdf0e7a363 100644 --- a/R/shiny.R +++ b/R/shiny.R @@ -48,10 +48,9 @@ renderPlotly <- function(expr, env = parent.frame(), quoted = FALSE) { # prepareWidget() makes it possible to pass different non-plotly # objects to renderPlotly() (e.g., ggplot2, promises). It also is used # to inform event_data about what events have been registered - shiny::installExprFunction(expr, "func", env, quoted) - renderFunc <- shinyRenderWidget( - plotly:::prepareWidget(func()), plotlyOutput, env, quoted - ) + shiny::installExprFunction(expr, "func", env, quoted, assign.env = env) + expr <- quote(plotly:::prepareWidget(func())) + renderFunc <- shinyRenderWidget(expr, plotlyOutput, env, quoted) # remove 'internal' plotly attributes that are known to cause false # positive test results in shinytest (snapshotPreprocessOutput was added # in shiny 1.0.3.9002, but we require >= 1.1)