Consider a simple plotly scatterplot that is dependent on a user selection (via selectInput
) that selects the variable to plot on a particular axis. We want to update the plot with the click of a button, rather than when the user interacts with the selectInput
. So, we wrap the plot-update logic in an observeEvent
that takes a dependency on the button. The observeEvent
updates a reactiveValues
object that contains the plot. (This example uses reactiveValues
because we're demonstrating this with both ggplot and plotly plots.)
When the app is run, before clicking the actionButton
, changing the selected variable from selectInput
does not update the plot (as expected). However, after the actionButton
has been clicked once, any further change to the selectInput
invalidates the plotly plot instantly and causes it to re-render. This behaviour does not occur with the ggplot plot (which only updates when the actionButton
is clicked).
I've also tried wrapping the reactive value that defines the plotly plot in isolate
, and create an explicit dependency on the input$update_plts
button, but that makes no difference.
library(shiny)
library(ggplot2)
library(plotly)
ui <- {
fluidPage(
selectInput('select_xvar', label = 'select x var', choices = names(mtcars)),
actionButton('update_plts', 'Update plots'),
plotOutput('plt1'),
plotlyOutput('plt2')
)
}
server <- function(input, output, session) {
val <- reactiveValues(
plt1 = ggplot(mtcars) +
geom_point(aes(x = wt, y = mpg)
),
plt2 = plot_ly(mtcars,
x = ~wt,
y = ~mpg
)
)
observeEvent(input$update_plts, {
val$plt1 = ggplot(mtcars) +
geom_point(aes_string(
x = input$select_xvar,
y = 'mpg'
))
val$plt2 = plot_ly(mtcars,
x = ~get(input$select_xvar),
y = ~mpg)
})
output$plt1 <- renderPlot(val$plt1)
# initial attempt with no isolate
# output$pl2 <- renderPlotly(val$plt2)
# second attempt with isolate, still invalidates instantaneously
output$plt2 <- renderPlotly({
input$update_plts
isolate(val$plt2)
})
}
shinyApp(ui, server)
Any ideas why this is the case with plotly? The only reference to this I could find is a closed Github issue that is apparently unresolved.
Not sure why, but it works as expected when you isolate
inputs in the plot_ly
call:
val$plt2 = plot_ly(mtcars,
x = ~get(isolate(input$select_xvar)),
y = ~mpg)
You can then remove isolate
and actionButton
from renderPlotly
:
output$plt2 <- renderPlotly(val$plt2)