daattali / shinyjs

💡 Easily improve the user experience of your Shiny apps in seconds
https://deanattali.com/shinyjs
Other
734 stars 119 forks source link

Shinyjs functions are not working when Shiny module is loaded with insertUI() or renderUI() #204

Closed ppagnone closed 4 years ago

ppagnone commented 4 years ago

Hi Dean , I hope you are well, I am using your great package again and I have a problem with shinyjs functions as show/hide/html when I try to use insertUI() or renderUI() in shiny modules.

I think that is related to https://github.com/daattali/shinyjs/issues/136 , but that was closed because the user used other alternative. In my case I need to use the insertUI() because I am loading modules based on url params.

I attach a simple example with an app using 2 modules: the module1 use the module2 via insertUI() and callmodule(). The module2 have a div (id textsample) with a text and in the server have a observe() that try to modify the div content.

I was debugging and the UI is loading correctly before than Server module. If I avoid to use the insertUI and load the mod_ui2() directly in the UI of mod_ui1 that works correctly but is not enough for my current requirement.

library(shiny)
library(shinyjs)

#' Module UI 2
#' Will show a div with text (id textsample)
mod_ui2 <- function(id) {
  ns <- NS(id)
  fluidPage(
    shinyjs::useShinyjs(),
    div(id = ns("textsample"), 
        p("HELLO TO MODULE 2"))
  )
}
#' Module Server 2
#' Have an observer to modify the text of UI (textsample)
mod_server2 <- function(input,output, session){
  observe({
    shinyjs::html(id = "textsample", html = "TEXT MODIFIED IN MODULE 2")
  })
}

#' Module UI 1
#' Show a text and a div to load a module based on url params.
mod_ui1 <- function(id){
  ns <- NS(id)
  fluidPage(
    p("Here module1"),
    div(id = ns("page"))
  )
}

#' Module Server 1
#' Loading the "module2" but could be differentes modules based on url params.
mod_server1 <- function(input, output, session){

  observe({
    insertUI(paste0("#", session$ns("page")),
             ui = mod_ui2(session$ns("module2")))

    callModule(mod_server2, "module2")    
  })

}

shinyApp(function(id){
            fluidPage(
              mod_ui1("module1")
            )
         }, 
         function(input, output, session){
            callModule(mod_server1, "module1")
         }
)

If you have some idea, I would be grateful. Thanks in advance!

daattali commented 4 years ago

I don't have time to look into this right now. But for now can you look over #136 and read my comments and see if that's the issue you're seeing? I get a lot of "issue reports" from shinyjs users claiming that a function isn't working on dynamic UI, when the problem is that the shinyjs function is being called before the UI element exists on the page, so shinyjs can't do anything about that.

ppagnone commented 4 years ago

Thanks for your fast answer, I have read that issue and I checked that UI module is load before than server module, but don't seem be the problem. I will continue investigating.

daattali commented 4 years ago

Please verify that the UI element is added to the screen before the function is called, not that the module is created. When you add dynamic UI to shiny, it's not instant. That's what you need to test.

On Thu., Apr. 2, 2020, 17:47 Pablo Pagnone, notifications@github.com wrote:

Thanks for your fast answer, I have read that issue and I checked that UI module is load before than server module, but don't seem be the problem. I will continue investigating.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/daattali/shinyjs/issues/204#issuecomment-608107586, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAHIQFAHWEYHZQRQKKCTJH3RKUBVTANCNFSM4L25C5FA .

ppagnone commented 4 years ago

You are right, the insertUI() must be call with param "immediate = TRUE" to work otherwise the server module is loaded before than ui module.

Thanks for you help, I was checking a lot of examples and I didnt see using the immediate param in insertUI().

I close, best regards!