Closed Patrikios closed 1 year ago
Seems OK by adding outputOptions(output, "plot", suspendWhenHidden = FALSE)
.
If you do so, the nice loading effect of echarts is gone. Any better option?
Strange, I get the loading effect.
It seems this issue is specific to using {echarts4r}
in combination with selectizeInput()
. For example, plotOutput()
works as expected:
server = function(input, output) {
observeEvent(input$species, {
showModal(modalDialog(plotOutput("plot"), easyClose = TRUE, footer = NULL))
})
output$plot <- renderPlot({
ggplot(subset(iris, Species == input$species)) + geom_point(aes(Sepal.Length, Sepal.Width))
})
}
Also, I get the following JS error when running your example, so it seems the selectInput()
accessibility plugin is not compatible with {echarts4r}
.
As a workaround, you could consider selectInput()
with selectize = FALSE
, but I'm pretty sure a fix will have to come from https://github.com/JohnCoene/echarts4r
I would disagree that the problem is not present with ggplot2. Let us take a look at this video, that demonstrates that as well with ggpot2 plot, firstly the old values are displayed and then chang to the updated input. Is that an intention to have it like that?
Code:
library(shiny)
library(ggplot2)
app <- shinyApp(
ui = fluidPage(
selectInput(
"species",
"Select spiecies",
sort(unique(iris$Species)),
"virginica"
)
),
server = function(input, output) {
observeEvent(input$species, {
showModal(
modalDialog(
textOutput("heading"),
plotOutput("plot"),
easyClose = TRUE,
footer = NULL
)
)
})
output$heading <- renderText(input$species)
output$plot <- renderPlot({
ggplot(subset(iris, Species == input$species)) +
geom_point(aes(Sepal.Length, Sepal.Width))
})
}
)
runApp(app)
Ahh, sorry, I mis-understood the problem. Yes, it is intentional that the "outdated" version of the plot is shown before the "new" version. That's because, by default, shiny will not update outputs that aren't currently shown. As was suggested, https://github.com/rstudio/shiny/issues/3731#issuecomment-1328703158 is the typical way to opt-out of that behavior.
In this case, you could also consider creating a modal for each output that you want to show:
library(shiny)
library(ggplot2)
species <- levels(iris$Species)
app <- shinyApp(
ui = fluidPage(
selectInput(
"species", "Select spiecies", species, "virginica"
)
),
server = function(input, output) {
observeEvent(input$species, {
showModal(
modalDialog(
plotOutput(input$species),
easyClose = TRUE,
footer = NULL
)
)
})
lapply(species, function(x) {
output[[x]] <- renderPlot({
ggplot(subset(iris, Species == x)) +
geom_point(aes(Sepal.Length, Sepal.Width))
})
})
}
)
runApp(app)
Regardless of how you decide to implement this behavior, I don't think there is anything for the shiny team to do here, so I'll be closing the issue
I see what you mean now regarding the effect. I found a solution:
library(shiny)
library(echarts4r)
app <- shinyApp(
ui = fluidPage(
useShinyjs(),
selectInput(
"species",
"Select spiecies",
sort(unique(iris$Species)),
"virginica"
)
),
server = function(input, output) {
observeEvent(input$species, {
showModal(modalDialog(
tagList(renderEcharts4r(echart())),
footer = NULL,
easyClose = TRUE
))
})
echart <- reactive({
subset(iris, Species == input$species) |>
e_charts(Sepal.Length) |>
e_line(Sepal.Width) |>
e_tooltip(trigger = "axis")
})
}
)
runApp(app)
That is something new right there, somehow shortcircuiting the output object directly via render. Never seen it before. But works as I intended. Thnx.
A more bare bones (no shinyjs
dependency and no tagList
wrapper) app is here:
library(shiny)
library(echarts4r)
shinyApp(
ui = fluidPage(
selectInput(
"species",
"Select spiecies",
sort(unique(iris$Species)),
"virginica"
)
),
server = function(input, output) {
observeEvent(input$species, {
showModal(modalDialog(
renderEcharts4r(echart()),
footer = NULL,
easyClose = TRUE
))
})
echart <- reactive({
subset(iris, Species == input$species) |>
e_charts(Sepal.Length) |>
e_line(Sepal.Width) |>
e_tooltip(trigger = "axis")
})
}
) |> runApp()
https://user-images.githubusercontent.com/11005155/201293276-3d5215cf-d3c2-4cba-8a8e-f66bbc5e662c.mp4
System details
Output of
sessionInfo()
:Example application reprex
Describe the problem in detail
The default select input "virginica" dependent output renders Okay (as it is the first render outcome cached???) however the other 2 Species render only after, for a brief moment, the outcome of "virginica" is displyed, only then the correct output is to be seen.
Obviously, this happens only in modal dialogues, when you bind output directly into fluidPage, it works as expected.
This could be resolved assigning a custom "NS"ed output ID to each input via shiny module or a functional approach (which I tested and works), however I think that is not the idea behind having a simple output depending on simple input like in the example above, it should be working out of the box right without flash of old input value.