Functions and modules

We have now gone through a good number of Shiny applications that are focused on different topics. Imagine that we now have to develop a fully-fledged enterprise application with various functionalities as a Shiny application. As the application grows, so will the number of lines of code and its complexity. In situations such as these, applications can become unmanageable. We may also be rewriting the same kind of code repeatedly, thereby increasing the development time. Additionally, variables need to be scoped, which limits the reusability of names. To eliminate these obstacles, we can use modularization.

Modularization is nothing but the use of separating modules according to their functionality. Modules can be defined as a set of instructions that are written to accomplish a task. R programming is developed around modules. We repeatedly call functions for almost any task we want to perform. This means that we don't have to write more code, as is required in programming languages such as C, C++, or Java. We can use this programming paradigm with Shiny as well.

So far, we have coded UI and server functions in the Shiny application, with a number of components and input and output elements.We will now try to modify these in a simpler coding pattern with modules.

We can organize the code into two sections, based on two functions:

  • For creating UI elements
  • For loading server logic

We also have to stick to some naming conventions so that the code can be identified easily. The UI modules can be suffixed with Input, Output, or UI. Before going into too much detail, let's start by observing the simple application code that is available whenever we start the Shiny application, RStudio. This is given here:

# 
# This is a Shiny web application. You can run the application by clicking 
# the 'Run App' button above. 
# 
# Find out more about building applications with Shiny here: 
# 
#    http://shiny.rstudio.com/ 
# 
 
library(shiny) 
# Define UI for application that draws a histogram 
ui<- fluidPage( 
 
   # Application title 
titlePanel("Old Faithful Geyser Data"), 
 
   # Sidebar with a slider input for number of bins  
sidebarLayout( 
sidebarPanel( 
sliderInput("bins", 
                     "Number of bins:", 
min = 1, 
max = 50, 
value = 30) 
      ), 
 
      # Show a plot of the generated distribution 
mainPanel( 
plotOutput("distPlot") 
      ) 
   ) 
) 
 
# 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') 
   }) 
} 
 
# Run the application  
shinyApp(ui = ui, server = server)

We can see that this code from RStudio is simply written without modularization. Let's discuss in detail how we can modularize the UI and Server code of this application:

  • UI Code modularization: In the preceding code, one of the elements of the UI section is sliderInput. At the moment, there is only one sliderInput box, but there might be more, meaning we would have to write the same code again and again if we didn't use modularization. Let's develop a module for this. For the UI module, we need to give a name to the function, such asSliderbarInput. We also need to give an ID to each input element that we are using. In the function argument, therefore, we will add one ID parameter, which will be used to create a namespace using NS(). Right now, we only have one input element, but in the future we may want to add multiple elements. We will use tagList(). The UI module will now look as follows:
    SliderbarInput<-function(id){ 
 
    ns<-NS(id) 
 
    tagList( 
    sliderInput(ns("bins"), 
                    "Number of bins:", 
    min = 1, 
    max = 50, 
    value = 30) 
 
             ) 
    } 

We have now separated the input code from the UI code. We have to call this code from inside the UI whenever we want to put in a slider bar. In the following code, we can see that SliderbarInput("Simplesliderbar") has been called. This will call to the preceding code. "Simplesliderbar" is the ID given to sliderInput:

    ui<- fluidPage( 
 
       # Application title 
    titlePanel("Old Faithful Geyser Data"), 
 
       # Sidebar with a slider input for number of bins  
    sidebarLayout( 
    sidebarPanel( 
 
    SliderbarInput("Simplesliderbar") # call to function 
 
          ), 
 
          # Show a plot of the generated distribution 
    mainPanel( 
    plotOutput("distPlot") 
          ) 
       ) 
    ) 
  • Server Code modularization: In the server section of the original code, we are developing a calculation to render a plot. We will develop a module to perform this task. Our first task is to give a name to the function, such as Sliderbar. In the server module, the function has to have three arguments: Input, Output, and Session. The rest can be the input parameters the user wants to add. After that, we will write all the calculation code in this function. Our new module will look as follows:
    Sliderbar<-function(input,output,session){ 
      # 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') 
 
    } 

We now have to call the preceding code from the usingcallModule() server code. Here, we will pass the function to be called and the label or ID of the input element. The server code will look as follows:

server<- function(input, output) { 
 
output$distPlot<- renderPlot({ 
callModule(Sliderbar, "Simplesliderbar")  
# Simplesliderbar is coming from UI 
   }) 
} 
 

By doing this, we have recreated the application. However, we have to decide where we can define our modules. One option is to keep our modules in the preamble of a single file application or in a file that is sourced in the preamble of a single file. Another option is to put the modules in a global.r file, or a file that is sourced in the global file. Alternatively, we can wrap a module in a package that is loaded by the application.

The advantage of using modularization is that it makes the code reusable.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset