简体   繁体   中英

renderDataTable with actionButton in two shinydashboard tabs

I came across this issue while trying to user shiny::renderUI to generate a data table output via renderDataTable upon clicking an actionButton . This situation works fine until I try to implement two instances of the same thing in separate tabs. In this case, whichever button is clicked first (be it in tab 1 or tab 2) works correctly; but then the other tab's button doesn't produce the data table. Is there a way to get two buttons, in separate shinydashboard tabs, to render data tables independently?

The following shows reproducible code to demonstrate the issue. A small data frame is populated with random values. Clicking the action button calculates new numbers for the data table--but only for the first data table that is rendered.

library(shiny)
library(shinydashboard)

ui <- dashboardPage(
  dashboardHeader(title = "Test example"),
  dashboardSidebar(
    sidebarMenu(
      menuItem("Tab 1", tabName = "tab_1"),
      menuItem("Tab 2", tabName = "tab_2")
    )
  ),
  dashboardBody(
    tabItems(
      tabItem("tab_1",
        h2("Tab 1"),     
        fluidRow(
          actionButton("do_refresh_tab_1", "Refresh data")
        ),
        fluidRow(
            uiOutput("tab1")
        )
      ),
      tabItem("tab_2",
        h2("Tab 2"),    
        fluidRow(
          actionButton("do_refresh_tab_2", "Refresh data")
        ),
        fluidRow(
            uiOutput("tab2")
        )
      )
    )  
  )
)

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

  observeEvent(input$do_refresh_tab_1, {

    df <- data.frame(value = rnorm(3),
                          Measurement = rnorm(3),
                          stringsAsFactors = FALSE)

    output$tab1 <- renderUI({
      output$temp <- renderDataTable(df)
      dataTableOutput("temp")
    })
  })

  observeEvent(input$do_refresh_tab_2, {

    df <- data.frame(value = rnorm(3),
                          Measurement = rnorm(3),
                          stringsAsFactors = FALSE)

    output$tab2 <- renderUI({
      output$temp <- renderDataTable(df)
      dataTableOutput("temp")
    })
  })
}

shinyApp(ui, server)

Before we go to the solution, a couple of general rules of thumb.

  1. Avoid, in fact, never put a render call inside another render call.
  2. Never put a render call inside an observe call
  3. Never put a render call inside a reactive call

Each observe, reactive and render call should be standalone and must perform 1 task/function.

The reason why only the first click was working and the second click on the other tab was not, was because you were attempting to create multiple output bindings with the same id ( temp ).

Every output element must have its own unique id.

Also, using uiOutput and dataTableOutput for this use case is kinda redundant here.

Here is the simplified code,

library(shiny)
library(shinydashboard)

ui <- dashboardPage(
  dashboardHeader(title = "Test example"),
  dashboardSidebar(
    sidebarMenu(
      menuItem("Tab 1", tabName = "tab_1"),
      menuItem("Tab 2", tabName = "tab_2")
    )
  ),
  dashboardBody(
    tabItems(
      tabItem("tab_1",
              h2("Tab 1"),     
              fluidRow(
                actionButton("do_refresh_tab_1", "Refresh data")
              ),
              fluidRow(
                dataTableOutput("table1")
              )
      ),
      tabItem("tab_2",
              h2("Tab 2"),    
              fluidRow(
                actionButton("do_refresh_tab_2", "Refresh data")
              ),
              fluidRow(
                dataTableOutput("table2")
              )
      )
    )  
  )
)

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




    output$table1 <- renderDataTable({
      req(input$do_refresh_tab_1)
      df <- data.frame(value = rnorm(3),
                       Measurement = rnorm(3),
                       stringsAsFactors = FALSE)
      return(df)
    })

    output$table2 <- renderDataTable({
      req(input$do_refresh_tab_2)
      df <- data.frame(value = rnorm(3),
                       Measurement = rnorm(3),
                       stringsAsFactors = FALSE)
      return(df)
    })
}

shinyApp(ui, server)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM