Source and List: Organizing R Shiny Apps

[This article was first published on R – R-BAR, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Keeping R Shiny code organized can be a challenge. One method to organize your Shiny UI and Server code is to use a combination of R’s list and source functions. Another method to organize you’re Shiny code is through modularization techniques. Here though, we’re going concentrate on the list and source options.

If you feel comfortable with Shiny and want to get strait to the answer, check out the Solution section. Otherwise, read on!

Outline

  1. Difficulty Organizing Shiny UIs
    1. A UI Source Example That Usually Doesn’t Work
    2. When Source Fails in the UI
    3. Solution
    4. Usage Note
  2. Organizing the Shiny Server with Source
  3. Summary

Difficulty Organizing Shiny UIs

If you have a Shiny application with a lot of controls, it’s easy to get lost in the braces, parentheses and brackets. Using R’s list() and source() functions, we can make UI code much more manageable by moving components out to other files.

So how do you do it?

To get us started, we are going to work with the starter app provided in R studio. Click File →New →Shiny Web App… . A dialogue box will pop up. My setup details are shown below in the R-Studio dialogue box. Choose a working directory appropriate for you and press Create.

New Shiny App Dialogue Box

R-Studio will then show the code for the starter Shiny App. The demo code has 4 parts.

  • Load the Shiny Library
  • Define the UI
  • Define the Server
  • Run the app.

We are going to start on the UI portion of the Shiny app shown in the screen capture below. This particular UI can be broken down into two parts the “Side Bar Panel” [lines 9-13] and the “Main Panel” [lines 15-17]. What we are going to do is factor out the content in the Side Bar Panel to a file named Side_Panel_CTRL.R and the Main Panel content to a file named Main_Panel_OUTPUT.R.

UI Section of Shiny Starter Application

So, make the two new R scripts named Side_Panel_CTRL.R and Main_Panel_OUTPUT.R. From the app.R file, MOVE the sliderInput (lines 10-12 above) to the Side_Panel_Control.R file and the plotOutput (line 16) to the Main_Panel_OUTPUT.R. Make sure these two new files are saved in the same folder as your app.R file.

A UI Source Example that Usually Doesn’t Work

Once you have your files setup, add the source() statements into you app.R file as shown in the code snippet below (lines 8 & 12).

# Define UI for application that draws a histogram
ui <- fluidPage(
   titlePanel("List and Source UI"), # Title Page
   
   # Sidebar with a slider input for number of bins
   sidebarLayout(  
      sidebarPanel( # The Side Bar
        source(file = "Side_Panel_CTRL.R", local = T)
      ),
   # Show a plot of the generated distribution    
   mainPanel( 
        source(file="Main_Panel_OUTPUT.R", local=T)
      )
   )
)

Great your files are setup.

Press the Run App Button in R Studio and the app starts as you might expect. You'll notice that the word TRUE pops up at the bottom of the slider control and the plot. Not sure why this happens, but you can remove it by adding “[1]” to the end of the source() statement as shown in the screen capture below summarizing where we are right now.

UI Section of Shiny Starter Application - Source Only

Cool, but this is about as far as you're going to get with source command alone.

When Source Fails in the UI

The source command alone can fail in the UI sections of a Shiny app. To demonstrate, we are going to add just one additional control to our side panel control file. First, though, let me show you that adding one additional control works when I add it directly to the app.R file in the UI section:

UI Section of Shiny Starter Application. Two controls in app.

To the right of the code, you can see that the app works. Now let's see what happens when we move the following control code back to the Side_panel_CTRL.r file.

#Slider Input
  #Slider Control
  sliderInput("bins", "Number of bins:",
              min = 1, max = 50, value = 30
  ), 
  #text box control
  textInput("textBox1", label = "Enter Value")

OK, moved the code. Here is what the three files should look like and the result of trying to run them.

UI Section of Shiny Starter Application - source Causing error with two controls.

hmm… We had an error, and it seems to involve the syntax of the code we are sourcing… perhaps the comma. How do we fix this?

Solution

The simple fix is to wrap the code in your UI files with the list command as shown in the following few screen shots: Look specifically at lines 1 and 9 of the Side_Panel_CTRL.r file and 1 and 5 of Main_Panel_OUTPUT.r file.

UI Section of Shiny Starter Application - Source list solution.

Usage Note

I find the source() and list() combo to be particularly useful when I work with tabbed panels. A quick example is shown below with some tabPanel code on lines 11-12. The controls for these two panels are coded in the source files as described previously.

Shiny UI tabPanel source list combo example.

Organizing the Shiny Server with Source

Server side Shiny is good old fashioned R-code and can be easily sourced from an external file using the source() command without list.

source(
file = “[source file path]”,
local = True #
)

The only trick with server side Shiny is dealing with the reactive elements like “reactive({…})”. For these you need to put the source() command in place of the “…”. To illustrate consider the following two code snippets.

Out-of-the-box sever code looks something like this:

# Define server logic required to draw a histogram
server <- function(input, output) {
   output$distPlot <- renderPlot({
     # generate bins based on input$bins from ui.R
     x    <- faithful[, 2] 
     bins <- seq(min(x), max(x), length.out = input$bins + 1)
     # draw the histogram with the specified number of bins
     hist(x, breaks = bins, col = 'darkgray', border = 'white')
   })
}

If you source out lines 3 through 9 after the output$distPlot assignment to a file called Server_Plot.R, and leave the server code like this:

server <- function(input, output) {
   output$distPlot <- source(file="Server_Plot.R", local=T) 
  
}

You'll get an error:

“Error in .subset2(x, "impl”)$defineOutput(name, value, label) :
Unexpected list output for distPlot"

To avoid this error, keep the renderPlot({}) reactive element in the app.R file and source from within like so:

server <- function(input, output) {
   output$distPlot <- renderPlot({
     source(file="Server_Plot.R", local=T) 
   })
}

For the server side, that's it. You should also notice that compared to the UI side, we did not need to place the “[1]” at the end of the source command.

Summary

Shiny is a great tool for communicating data, but its easy to get lost in the braces, brackets, and parentheses. To help simplify your next Shiny application, try using the source-list combo and don't forget the “[1]” at the end of the source statement, or you'll have a while bunch of TRUEs running around. On the server side, we need to be careful around reactive elements.

The post Source and List: Organizing R Shiny Apps appeared first on R-BAR.

To leave a comment for the author, please follow the link and comment on their blog: R – R-BAR.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)