daattali/shinyjs

onclick can't be used for elements in renderUI

Closed this issue · 7 comments

First of all, thanks for this great package.

The issue is that onclick won't work for elements generated in renderUI.

Below is the minimal reproducible example.

Work APP

library(shiny)
shinyApp(
  ui = renderUI({
    sidebarLayout(
      sidebarPanel(
        shinyjs::useShinyjs(),
        a(id = "test_a", "Show/hide advanced info"),
        shinyjs::hidden(
          div(id = "test_div",
              textInput("test_email", "Email:", value = "abc@abc.com")
          )
        )
      ),
      mainPanel()
    )
  }),
  server = function(input, output) {
    shinyjs::onclick("test_a", 
                     shinyjs::toggle(id = "test_div", anim = TRUE))
  }
)

Won't Work APP

library(shiny)
shinyApp(
  ui = uiOutput("ui"),
  server = function(input, output) {
    output$ui <- renderUI({
      sidebarLayout(
        sidebarPanel(
          shinyjs::useShinyjs(),
          a(id = "test_a", "Show/hide advanced info"),
          shinyjs::hidden(
            div(id = "test_div",
                textInput("test_email", "Email:", value = "abc@abc.com")
            )
          )
        ),
        mainPanel()
      )
    })
    shinyjs::onclick("test_a", 
                     shinyjs::toggle(id = "test_div", anim = TRUE))
  }
)

Any ideas?

Thanks!

Hi @shrektan , please see the discussion in #25 , this is a duplicate of that issue. In short: this is a shiny/javascript limitation, because when you call onclick() the javascript says "whenever the user clicks on this object, do this", but that object doesn't exist yet. In order to get around that, you need to call the onclick() function only after the renderUI is finished. Currently shiny does not provide an easy way to know when that happens, but it will be possible in the future. If you have any more comments, please continue discussion on the other issue

Thanks! I get it:D

(oops, I referenced this issue in the previous commit message, but it's wrong, that commit is unrelated to this issue)

it's ok~ 🍡

@shrektan I fixed this and should now work. Note that your code won't work exactly as it is because you also have the useShinyjs() call inside the renderUI(). If you move the useShinyjs() into the main UI, the rest will work fine. Here's a modification of your code which now works:

shinyApp(
  ui = tagList(
    useShinyjs(),
    uiOutput("ui")
  ),
  server = function(input, output) {
    output$ui <- renderUI({
      sidebarLayout(
        sidebarPanel(
          a(id = "test_a", "Show/hide advanced info"),
          hidden(
            div(id = "test_div",
                textInput("test_email", "Email:", value = "abc@abc.com")
            )
          )
        ),
        mainPanel()
      )
    })
    onclick("test_a", 
                     toggle(id = "test_div", anim = TRUE))
  }
)

Let me know if this works for you

@daattali Thanks so much. It works!

I also test the function disabled in my developing project. It works fine, too!

I really love this package:D Helps us so much!
Thanks again!

If you like it, help me get the word out and let people know about it :)