Search code examples
rshinymoduledtbox

Hide initially displayed box and table in modularized shiny app after clicking actionButton()


Here I want to hide an initially displayed box and datatable after clicking an actionButton in a modularized shiny app but only the box is displayed and then remains stable.

app.r

library(shiny)
library(shinyjs)
library(shinydashboard)
library(shinyWidgets)
library(dplyr)

# Load the modules
source("sideUI.R")
source("sideServer.R")
source("tabUI.R")
source("tabServer.R")

# Build UI & server and then run the app
ui <- dashboardPage(
  dashboardHeader(title = "Text Hiding Example"),
  dashboardSidebar(sideUI("side")),  # Sidebar with the action button
  dashboardBody(
    useShinyjs(),  # Initialize shinyjs
    tabUI("tabPL")  # Table UI module
  )
)

server <- function(input, output, session) {
  # Use the reactive in another module
  btn_input <- sideServer("side")
  tabServer("tabPL", btn = btn_input$btn)
}

shinyApp(ui, server)

tabUI.R

tabUI <- function(id) {
  ns <- NS(id)
  
  tagList(
    div(
      id = ns("showtab"),
      box(
        title = h3("Check our data", style = 'font-size:20px;color:white;
                     font-family: "Georgia", Times, "Times New Roman", serif;'), 
        status = "primary", 
        solidHeader = TRUE,
        width=12,
        height = 430,
        collapsible = TRUE,
        tagList(
          dataTableOutput(ns("table"),height = 400)))
    )
  )
}

tabServer.R

tabServer <- function(id, btn) {
  moduleServer(
    id,
    function(input, output, session) {
      ns <- session$ns  # Namespace function
      
      # Observe button click event
      observeEvent(btn(), {
        output$table<-renderDataTable({
          datatable(iris)
        })
        
        shinyjs::hide("showtab")  # Hide the text with correct namespace
      })
    }
  )
}

sideUI.R

sideUI <- function(id) {
  ns <- NS(id)
  tagList(
    actionButton(ns("action"), "Hide Tab")
  )
}

sideServer.R

sideServer <- function(id) {
  moduleServer(
    id,
    function(input, output, session) {
      return(btn = reactive(input$action))  # Return the button input as reactive
    }
  )
}

Solution

  • A few things:

    1. You must wrap btn = reactive(input$action)) in list() in sideServer.R (otherwise btn_input is not a list containing an element named btn). Alternatively, pass btn_input instead of btn_input$btn in app.R. You need to do one or the other [this was the same issue in your previous question]

    2. Use DT::renderDT() and DT::DTOutput(), instead of shiny::datatableOutput() and shiny::renderDataTable()

    3. tabServer.R() should be re-written like this:

    tabServer <- function(id, btn) {
      moduleServer(
        id,
        function(input, output, session) {
          output$table<-DT::renderDT({DT::datatable(iris)})
          # Observe button click event
          observeEvent(btn(), shinyjs::hide("showtab"))
        }
      )
    }
    
    1. tabUI.R should be adjusted:
    tabUI <- function(id) {
      ns <- NS(id)
      
      tagList(
        div(
          id = ns("showtab"),
          box(
            DT::DTOutput(ns("table")),
            title = h3("Check our data", style = 'font-size:20px;color:white;
                         font-family: "Georgia", Times, "Times New Roman", serif;'), 
            status = "primary", 
            solidHeader = TRUE,
            width=12,
            height = 430,
            collapsible = TRUE
          )
        )
      )
    }
    

    Here is a full version, all within single file:

    library(shiny)
    library(shinyjs)
    library(shinydashboard)
    library(shinyWidgets)
    library(dplyr)
    
    sideUI <- function(id) {
      ns <- NS(id)
      tagList(
        actionButton(ns("action"), "Hide Tab")
      )
    }
    
    sideServer <- function(id) {
      moduleServer(
        id,
        function(input, output, session) {
          return(list(btn = reactive(input$action)))  # Return the button input as reactive
        }
      )
    }
    
    tabUI <- function(id) {
      ns <- NS(id)
      
      tagList(
        div(
          id = ns("showtab"),
          box(
            DT::DTOutput(ns("table")),
            title = h3("Check our data", style = 'font-size:20px;color:white;
                         font-family: "Georgia", Times, "Times New Roman", serif;'), 
            status = "primary", solidHeader = TRUE, width=12, height = 430, collapsible = TRUE
          )
        )
      )
    }
    
    tabServer <- function(id, btn) {
      moduleServer(
        id,
        function(input, output, session) {
          output$table<-DT::renderDT({DT::datatable(iris)})
          # Observe button click event
          observeEvent(btn(), shinyjs::hide("showtab"))
        }
      )
    }
    
    # Build UI & server and then run the app
    ui <- dashboardPage(
      dashboardHeader(title = "Text Hiding Example"),
      dashboardSidebar(sideUI("side")),  # Sidebar with the action button
      dashboardBody(
        useShinyjs(),  # Initialize shinyjs
        tabUI("tabPL")  # Table UI module
      )
    )
    
    server <- function(input, output, session) {
      # Use the reactive in another module
      btn_input <- sideServer("side")
      tabServer("tabPL", btn = btn_input$btn)
    }
    
    shinyApp(ui, server)