rshinyshiny-servershinyappsshinymodules

Use source() with Shiny Modules


I have a Shiny app that I am trying to "modularize". I have an issue that my subtab tabPanel tab_Summary is not recognized when I separate it in another R file.

If I place the creation of the tab_Summary inside the ui.R it works, but if I want to be able to have this subtab in another file like showed in the following scripts, then I get error that object 'tab_Summary' not found :

The 0_tab_Summary_ui.R placed in the folder 'C:/Users/ROG/Downloads/example_shiny/Shiny_Modules':

tab_Summary <- tabPanel('Summary',  

         fluidRow(
           column(width = 3,
                  htmlOutput("Summary_Number_ui")
                  
                  
           )
)
         
         
)

The ui.R script:

setwd(paste0(main_working_dir, "Shiny_Modules"))
source("0_tab_Summary_ui.R")

ui <- navbarPage(
  
  title=div("SHINY DASHBOARD"),
  
  tab_Summary
  
)

The server.R script:

server <- function(input, output, session) {
    
  output$Summary_Number_ui <- renderUI({
    HTML(paste0("<div id='mydiv'><font size='5'><font color=\"#0d0a36\"> Total Number of Accounts: <b>",  726431 , "</b></div>"))
  })


}

The app.R script:

library(shiny)

local_working_dir <- "C:/Users/ROG/Downloads/example_shiny/"
main_working_dir <- local_working_dir
setwd(main_working_dir)

shinyApp(ui, server)

And below the ui.R script that does not show any error but is not modularized:

setwd(paste0(main_working_dir, "Shiny_Modules"))
source("0_tab_Summary_ui.R")

ui <- navbarPage(
  
  title=div("SHINY DASHBOARD"),
  
  # tab_Summary
  
  tab_Summary <- tabPanel('Summary',

                          fluidRow(
                            column(width = 3,
                                   htmlOutput("Summary_Number_ui")


                            )
                          )


  )

  
)

Solution

  • Try to learn how to use modules in Shiny, roughly global.R "includes" all your modules and those files have a module specific UI and a Server part that belong together. In the ui.R you define your layout and call the specific module UI part, same for the server.R. This way you keep all code for one module together, which makes it nicely scalable. Also note that whatever settings you may want to use and define, global.R is excecuted once upon the start of your app, while all code within your server.R server function is run upon every browser refresh.

    global.R

    # Global.R is loaded once at App start (not at browser refresh!)
    
    # load all libraries
    library("shiny")
    
    # source all your modules here
    source("modules/MyTabModule.R")
    

    ui.R

    ui <- navbarPage(
      
      title=div("SHINY DASHBOARD"),
      
      MyTabModuleUI("Summary_Number_ui")
      
    )
    

    server.R

    server <- function(input, output, session) {
      
      MyTabModuleServer("Summary_Number_ui")
      
      
    }
    

    modules/MyTabModule.R

    MyTabModuleUI <- function(id) {
      
      ns <- NS(id)
    
      tabPanel('Summary',
        fluidRow(
          column(
            width = 3,
            htmlOutput(ns("Summary_Number_ui"))
          )
        )
      )
      
    }
    
    MyTabModuleServer <- function(id) {
      
      moduleServer(id, function(input, output, session) {
        
        output$Summary_Number_ui <- renderUI({
          HTML(paste0("<div id='mydiv'><font size='5'><font color=\"#0d0a36\"> Total Number of Accounts: <b>",  726431 , "</b></div>"))
        })
        
      })
      
    }