Daniel Rodak
Daniel Rodak

Reputation: 158

Access by jQuery UI elements created in server part of Shiny App

I want to pass to Shiny ID of an element of specific pseudo-class when it is clicked. Everything is working fine if UI elements are created in UI part of Shiny app. But when UI is created on server side (by renderUI) it doesn't work. Below is reproducible example.

library(shiny)
library(shinyjs)

ui <- fluidPage(
  useShinyjs(),
  fluidRow(
    tags$div(id = "ui1", class = 'shiny-html-output shiny-bound-output',
      tags$a(id = "ID1", class = "my-class", href = "#", 'Link 1')
    ),
    uiOutput("ui2")
  )
)

server <- function(input, output) {
  output$ui2 <- renderUI({
    tags$a(id = "ID2", class = "my-class", href = "#", 'Link 2')
  })

  shinyjs::runjs(
  '$(document).ready(function(){
    $(".my-class").click(function(){
      alert($(this).attr("id"));
    });
  });')
}

shinyApp(ui, server)

Upvotes: 5

Views: 764

Answers (1)

$(document).ready approach won't work because server will not render it outputs until the DOM is ready. Use session$onFlushed instead, with once parameter set to TRUE, then shiny will run the function only once, not on every session flush.

This will work:

library(shiny)
library(shinyjs)

script <- "$('.my-class').click(function(){
alert($(this).attr('id'));
});"

ui <- fluidPage(
  useShinyjs(),
  fluidRow(
    tags$div(id = "ui1", class = 'shiny-html-output shiny-bound-output',
             tags$a(id = "ID1", class = "my-class", href = "#", 'Link 1')
    ),
    uiOutput("ui2")
  )
)

server <- function(input, output, session) {

  output$ui2 <- renderUI({
    tags$a(id = "ID2", class = "my-class", href = "#", 'Link 2')
  })


  session$onFlushed(function() {
    shinyjs::runjs(script)
  }, once=TRUE)

}

shinyApp(ui, server)

Upvotes: 2

Related Questions