Search code examples
rshinyhideshowdt

RShiny: Hiding / Showing a Table based on Radio Buttons


I have two tables and I'm trying to show one at a time based on user input in radio buttons. If the input from the radio buttons is "table", i'd like to show table1. If the input is else i'd like to show table2.

  observeEvent(input$visuBtn,{
    req(input$visuBtn)
    print(input$visubtn)
    if(input$visuBtn == "table"){
      hide("table2")
      #DT::dataTableOutput("table1")
      renderUI(
        DT::dataTableOutput("table1")
      )
    }else{
      print("Should show table2")
      # removeUI(
      #   selector = "table"
      # )
      renderUI(
        DT::dataTableOutput("table2")
      )
      #DT::dataTableOutput("table2")
      #show("table2")
    }
  })

I've tried doing this by showing and hiding the two tables and can't figure out how to get that to work. I"ve also tried using renderUI as well. What would be the best methodology to go about this?

     mainPanel(
       tabsetPanel(id = "sim.tabset",
         tabPanel(title = "Results",
                  # tableOutput("table")
                  DT::dataTableOutput("table"),
                  DT::dataTableOutput("table2")


         ),

         )
             

Solution

  • Depending on your app, you can toggle the visibility of the table in the frontend with a little bit of javascript. In the UI, create a button and wrap the dataTableOutput in a generic container.

    # some where in your UI
    actionButton("toggleTable", "Toggle Table"),
    tags$div(
        id = "tableContainer",
        DT::dataTableOutput("table")
    )
    ...
    

    There are many ways to toggle the visibility of an element (changing the display properties, toggling css classes, modifying other attributes, etc.). The following function toggles the html attribute hidden when the button is clicked. This can be defined in the UI using the tags$script function or loaded from an external javascript file.

    const btn = document.getElementById('toggle');
    const elem = document.getElementById('tableContainer');
    btn.addEventListener('click', function(event) {
        if (elem.hasAttribute('hidden')) {
            elem.removeAttribute('hidden');
        } else {
            elem.setAttribute('hidden', '');
        }
    });
    

    In the server, render the datatable as normal and you can remove the toggling (unless you need additional things to happen when the button is clicked).

    Here is the full example.

    library(shiny)
    
    shinyApp(
        ui = tagList(
            tags$main(
                id = "main",
                tags$h1("Collapsible Table Example"),
                actionButton("toggleTable", "Toggle Table"),
                tags$div(
                    id = "tableContainer",
                    DT::dataTableOutput("table")
                )
            ),
            tags$script(
                type = "text/javascript",
                "
                const btn = document.getElementById('toggleTable');
                const elem = document.getElementById('tableContainer');
                btn.addEventListener('click', function(event) {
                    if (elem.hasAttribute('hidden')) {
                        elem.removeAttribute('hidden');
                    } else {
                        elem.setAttribute('hidden', '');
                    }
                });
                "
            )
        ),
        server = function(input, output, session) {
            output$table <- DT::renderDataTable({
                data.frame(
                    group = sample(c("A", "B"), 20, replace = TRUE),
                    x = rnorm(n = 20, mean = 50, sd = 2),
                    y = rnorm(n = 20, mean = 50, sd = 2)
                )
            })
        }
    )