rstudio / shiny

Easy interactive web applications with R
https://shiny.posit.co/
Other
5.36k stars 1.87k forks source link

Calling `el.trigger("hidden")` in JavaScript doesn't work on elements that are being animated to be hidden #3831

Open daattali opened 1 year ago

daattali commented 1 year ago

Originally reported in https://github.com/daattali/shinyjs/issues/266

When an element is being hidden from the DOM, a trigger("hidden") javacript call needs to be made on that element, to notify shiny to not render it anymore. The classic way to hide an element is using the .hide() method. However, it seems like elements that are being hidden using animation javascript do not properly get hidden in the reactive graph. Example:

library(shiny)

jscode <- "
Shiny.addCustomMessageHandler('hide', function(m) { $('#out').fadeOut(); $('#out').trigger('hidden'); });
Shiny.addCustomMessageHandler('show', function(m) { $('#out').fadeIn(); $('#out').trigger('shown'); });
"

ui <- fluidPage(
  tags$script(HTML(jscode)),
  actionButton("hide", "hide"),
  actionButton("show", "show"),
  numericInput("num", "num", 5),
  textOutput("out")
)

server <- function(input, output, session) {
  output$out <- renderText({
    print("rendering")
    input$num
  })
  observeEvent(input$hide, session$sendCustomMessage('hide', list()))
  observeEvent(input$show, session$sendCustomMessage('show', list()))
}

shinyApp(ui, server)

In this code, an element is being hidden using jquery's fadeOut(). You can see that despite triggering the hidden event, the output still gets rendered. A similar thing happens when using slideUp() instead of fadeOut().

It seems that if you make the animation very fast, for example using fadeOut(5) (5 milliseconds), then the trigger does hold.

I noticed that if I add a callback function to the animation fadeOut(500, function() { $(this).trigger('hidden'); }) then it does work correctly. Because of this, my theory is that when hidden is triggered, shiny looks at the element, and only acts if the element has display:none.

cpsievert commented 1 year ago

I'm pretty sure https://github.com/rstudio/shiny/pull/3682 (using ResizeObserver()/IntersectionObserver()/MutationObserver() to detect changes in size/visibility) would solve this (as well as a whole other set of issues)