0

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")


                            )
                          )


  )

  
)
ML_Enthousiast
  • 1,147
  • 1
  • 15
  • 39
  • So you are trying to place the modules in a central directory and use them from different shiny apps? That's not a good idea (and it won't work if you want to deploy this to a server such as shinyapps). Instead, make an R package of your generic modules and use that in your shiny applications. – Remko Duursma Jan 09 '23 at 12:43
  • no I have only one shiny app. What I am trying to achieve is to have one R script per tabPanel, and be able to call these R script from main `app.R` – ML_Enthousiast Jan 09 '23 at 14:08
  • 2
    OK then I misunderstood. 1) do not use setwd(), 2) place the module in a subdirectory e.g. `modules` and then place in `global.R` : `source("modules/mymodule.R")` – Remko Duursma Jan 09 '23 at 14:23
  • As mentioned, using `setwd` is problematic. But `source` *also* has significant issues. I created the package [‘box’](https://github.com/klmr/box) specifically to fix these issues. – Konrad Rudolph Jan 09 '23 at 15:57

1 Answers1

1

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>"))
    })
    
  })
  
}
Merijn van Tilborg
  • 5,452
  • 1
  • 7
  • 22