Home > Back-end >  Update shiny UI only when tab is selected
Update shiny UI only when tab is selected

Time:02-02

I have a Shiny dashboard with multiple tabs. In one of the tabs, a slow database query fills the choices for a dropdown menu. I want the slow database query to execute only when the relevant tab is selected.

In the following ReprEx, the slowDatabaseQuery is executed at launch and blocks the R process.

library(shiny)

ui <- fluidPage(
  tabsetPanel(
    tabPanel(
      "panel1", 
      "Panel 1 content"
    ),
    tabPanel(
      "panel2", 
      "Panel 2 content",
      selectizeInput(
        "selected", 
        label = "Selector", 
        choices = NULL
      ),
      verbatimTextOutput("text")
    )
  )
)

server <- function(input, output, session) {
  slowDatabaseQuery <- reactive({
    Sys.sleep(5)
    return(c("C", "D"))
  })
  
  observe(
    updateSelectizeInput(
      session, 
      "selected", 
      choices = slowDatabaseQuery(), 
      selected = "C", 
      server = TRUE
    )    
  )
  
  output$text <- renderText(input$selected)
}

shinyApp(ui = ui, server = server)

A partial solution would be using renderUI() instead of updateSelectizeInput(). However, I would like to use the server = TRUE argument which is only available in updateSelectizeInput() and do not like that it would take the UI element a long time to appear.

CodePudding user response:

We can provide your tabsetPanel with an id and observe the selections via observeEvent.

There are two different options in the code below.

  1. The DB query is done each time tab2 is selected.
  2. The DB query is done the first time tab2 is selected in the current shiny-session (commented out).

library(shiny)

ui <- fluidPage(
  tabsetPanel(
    id = "tabsetPanelID",
    tabPanel(
      "panel1", 
      "Panel 1 content"
    ),
    tabPanel(
      "panel2", 
      "Panel 2 content",
      selectizeInput(
        "selected", 
        label = "Selector", 
        choices = NULL
      ),
      verbatimTextOutput("text")
    )
  )
)

server <- function(input, output, session) {
  
  slowDatabaseQuery <- reactive({
    Sys.sleep(5)
    return(c("C", "D"))
  })
  
  observeEvent(input$tabsetPanelID,{
    if(input$tabsetPanelID == "panel2"){
      updateSelectizeInput(
        session,
        "selected",
        choices = slowDatabaseQuery(),
        selected = "C",
        server = TRUE
      )
    }
  })
  
  # observeEvent(input$tabsetPanelID == "panel2", {
  #     updateSelectizeInput(
  #       session,
  #       "selected",
  #       choices = slowDatabaseQuery(),
  #       selected = "C",
  #       server = TRUE
  #     )
  # }, once = TRUE) # should the query be done only once or each time the tab is selected?
  
  output$text <- renderText(input$selected)
}

shinyApp(ui = ui, server = server)
  •  Tags:  
  • Related