1

In shiny apps we can add javascript code to run when a widget has rendered using onRender from library(htmlwidgets). The same does not seem to work for the default render* functions from shiny. Is there a way to achieve something similar for these render functions?

The app below shows alerts whenever the plotly and leaflet widgets are rendered, but not for renderUI and renderPlot.

library(shiny)
library(plotly)
library(leaflet)
library(htmlwidgets)

ui <- fluidPage(
  actionButton('a1','a1'),
  fluidRow(
    column(
      width=6,
      plotlyOutput('plt'),
      plotOutput('p2')
    ),
    column(
      width=6,
      uiOutput('foo'),
      leafletOutput('map')
    )
  )
)

server <- function(input, output, session) {
  
  output$foo <- renderUI({
    input$a1
    tagList(runif(1)) %>% 
      onRender('function() {alert("renderUI works");}')
  })
  output$plt <- renderPlotly({
    input$a1
    plot_ly(type='scatter', mode='markers', x=runif(10)) %>% 
      onRender('function() {alert("plotly works");}')
  })
  output$p2 <- renderPlot({
    input$a1
    hist(runif(50)) %>% 
      onRender('function() {alert("renderPlot works");}')
  })
  output$map <- renderLeaflet({
    input$a1
    leaflet() %>% 
      addTiles() %>% 
      onRender('function() {alert("leaflet works");}')
  })
}

shinyApp(ui, server)

1 Answer 1

2

onRender refers to rendering a htmlwidget not to shiny's render* functions.

You can use it without shiny.

onRender expects a HTML widget object and accordingly doesn't work with e.g. tags - see ?onRender:

Use this function to supplement the widget's built-in JavaScript rendering logic with additional custom JavaScript code, just for this specific widget object.

You can use library(shinyjs) instead to realize a similar behaviour:

library(shiny)
library(plotly)
library(leaflet)
library(htmlwidgets)
library(shinyjs)

ui <- fluidPage(
  useShinyjs(),
  actionButton('a1','a1'),
  fluidRow(
    column(
      width=6,
      plotlyOutput('plt'),
      plotOutput('p2')
    ),
    column(
      width=6,
      uiOutput('foo'),
      leafletOutput('map')
    )
  )
)

server <- function(input, output, session) {
  output$foo <- renderUI({
    input$a1
    runjs('alert("renderUI works");')
    tagList(p("p-tag"))
  })
  output$plt <- renderPlotly({
    input$a1
    plot_ly(type='scatter', mode='markers', x=runif(10)) %>% 
      onRender('function() {alert("plotly works");}')
  })
  output$p2 <- renderPlot({
    input$a1
    runjs('alert("renderPlot works");')
    hist(runif(50))
  })
  output$map <- renderLeaflet({
    input$a1
    leaflet() %>% 
      addTiles() %>% 
      onRender('function() {alert("leaflet works");}')
  })
}

shinyApp(ui, server)
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you. Would you know how we can write raw JS to be used on the widget once rendered?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.