Shiny module design patterns: Pass module input to other modules

[This article was first published on R – It's a Locke, 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.

Following on from looking at the shiny modules design pattern of passing an input value to many modules, I’m now going to look at a more complex shiny module design pattern: passing an input from one module to another.

TL;DR

Return the input in a reactive expression from within the server call. Store the callModule() result in a variable. Pass the variable into arguments for other modules. Steal the code and, as always, if you can improve it do so!

Starting out

For the purposes of this post, I’ll be morphing the dummy application that Rstudio produces when you use New file > Shiny app. I’ve created a repository to store these design patterns in and the default shiny app that will be converted / mangled is the 01_original.R file.

input value being directly used in shiny app
input value being directly used in shiny app

The next step along was passing a top-level input to many modules. See file 02_singlegloballevelinput.R for the end to end solution.

Store input in a reactive value to pass value onto modules
Store input in a reactive value to pass value onto modules

Pass module input to other modules

Make a module that contains inputs

A module must have a server function and can optionally have UI and Input functions. We need a module that has an input function so our skeleton for our setup values is

setupInput <- function( id ){
ns<-NS(id)

}

Input parameters must be held in a tagList() so that the shiny UI knows to handle them like other directly mentioned inputs. The setupInput function can contain any number of inputs, including the bins input that used to be a global input.

setupInput<-function(id){
  ns<-NS(id)
  tagList(
  sliderInput(ns("bins"), "Number of bins:",
              min = 1,  max = 50, value = 30)
  )
}

Output the input value

In the module with the input parameters, we may need to do stuff with the value and also make it available for other modules. To make the input parameter’s value available we need to put it within a reactive expression and output the expression as the return() value of the module.

setup<-function(input,output,session){
  bins<-reactive({input$bins})
  return(bins)
}

Make a module that accepts additional arguments

The vanilla module server function construct is function(input,output,session){}. There isn’t room for extra parameters to be passed through so we have to make space for one. In this case, our module skeleton that will hold our histogram code is

charts <- function( input, output, session, bins) {

}

When we use modules, they have to be called in the server function of a shiny app but they don’t have to be stored in a variable. If a module isn’t stored then whatever values are returned by an explicit return() statement will be lost and calling a module with the same ID more than once will result in errors, so to be able to pass the return value to multiple modules we must store it and then use it.

bins<-callModule(setup,"setupA")
callModules(charts, "chartA", bins)

Use the reactive value

When you reference a reactive value, you reference it like a function. We need to use bins() instead so that the result of the reactive value is returned.

Instead of bins <- seq(min(x), max(x), length.out = input$bins + 1) in our original, when we use our reactive value in our chart module, it becomes:

chart <- function(input, output, session, bins) {
  output$distPlot <- renderPlot({
    x    <- faithful[, 2]
    bins <- seq(min(x), max(x), length.out = bins() + 1)
    hist(x,
         breaks = bins,
         col = 'darkgray',
         border = 'white')
  })
}

Putting it together

To be able to pass an input value from one module to another, you need to:

  1. Make a module that returns a reactive expression for the input value
  2. Store the callModule results in a variable
  3. Add an argument to your module’s server function arguments
  4. Pass the name of the variable to the module
  5. Use argument() not argument within the module’s server function main code

See file 03_inputmodule.R for the end to end solution.

Store callModule to pass into other modules

Further study

The post Shiny module design patterns: Pass module input to other modules appeared first on It's a Locke.

To leave a comment for the author, please follow the link and comment on their blog: R – It's a Locke.

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)