class: center, middle, inverse, title-slide # Shiny Modules: Why you might want to use them ### Ted Laderas ### DNAnexus ### 2021-05-13 --- # Why Modules? - Motivating example - Why? - module code --- # Motivating Example - An ui that lets you pass in a dataset - Lets you select columns from that dataset - Want multiple plots in the same app --- <img src="module1.png"> --- # Using Shiny modules .pull-left.tiny[ ## ui <code class ='r hljs remark-code'>ui <- fluidPage( <br> <span style="background-color:#cdecff">select_hist_ui</span>(id = "<span style="background-color:#ffb700">mtcars_module</span>", <br> var_choices = mtcars_var_choices)<br> )</code> - note that .bg-lightest-blue[`select_hist_ui()`] is a function that takes an `id` argument - uses an `id` called .bg-gold[`mtcars_module`] ] .pull-right.tiny[ ] --- # Using Shiny modules .pull-left.tiny[ ## ui <code class ='r hljs remark-code'>ui <- fluidPage( <br> <span style="background-color:#cdecff">select_hist_ui</span>(id = "<span style="background-color:#ffb700">mtcars_module</span>", <br> var_choices = mtcars_var_choices)<br> )</code> ] .pull-right.tiny[ ## server <code class ='r hljs remark-code'>server <- function(input, output) {<br> <span style="background-color:#cdecff">select_hist_server</span>(id="<span style="background-color:#ffb700">mtcars_module</span>", <br> data=mtcars)<br>}</code> - Note that we have a function .bg-lightest-blue[`select_hist_server()`] - Also uses the `id` .bg-gold[`"mtcars_module"`] ] --- # Reusing code .pull-left.tiny[ ## ui <code class ='r hljs remark-code'>ui <- fluidPage( <br> <span style="background-color:#cdecff">select_hist_ui</span>(id = "mtcars_module", <br> var_choices = mtcars_var_choices),<br> <span style="background-color:#cdecff">select_hist_ui</span>(id = "<span style="background-color:#ffb700">penguin_module</span>",<br> var_choices = penguin_choices)<br> )</code> - note we have two .bg-lightest-blue[`select_hist_ui()`] functions - the second one has the `id` of .bg-gold[`penguin_module`] ] .pull-right.tiny[ ] --- # Reusing code .pull-left.tiny[ ## ui <code class ='r hljs remark-code'>ui <- fluidPage( <br> <span style="background-color:#cdecff">select_hist_ui</span>(id = "mtcars_module", <br> var_choices = mtcars_var_choices),<br> <span style="background-color:#cdecff">select_hist_ui</span>(id = "<span style="background-color:#ffb700">penguin_module</span>",<br> var_choices = penguin_choices)<br> )</code> ] .pull-right.tiny[ ## server <code class ='r hljs remark-code'>server <- function(input, output) {<br> <span style="background-color:#cdecff">select_hist_server</span>(id="mtcars_module", <br> data=mtcars)<br> <br> <span style="background-color:#cdecff">select_hist_server</span>(id="<span style="background-color:#ffb700">penguin_module</span>", <br> data=penguins)<br>}</code> - Note that we have two functions .bg-lightest-blue[`select_hist_server()`] - The second one use the `id` .bg-gold[`"penguin_module"`] - We can have two different plots/interfaces! ] --- # Two modules, two datasets .pull-left[ - dataset is `mtcars` <img src="module1.png" width=500> ] .pull-right[ - dataset is `penguins` <img src="module2.png" width=400> ] --- # You may want to use Shiny Modules if: - You want to reuse your code, especially in the same app - You are tired of thinking up unique ids for all the elements in your app - You need to break up a monolithic shiny application into pieces - Separate presentation from code --- # Maybe not: - Your app is a one and done - single version - It doesn't have that many controls --- # ui module <code class ='r hljs remark-code'>select_hist_ui <- function(id, var_choices){<br> #initialize a namespace ID function - our key to our namespace<br> <span style="background-color:#ffb700">ns <- NS(id)</span><br> <br> #return a tagList with our ui elements<br> tagList(<br> #note we have to wrap the input id in our namespace function ns()<br> selectInput(inputId = <span style="background-color:#ffb700">ns("x_var")</span>, label="Select X Variable", <br> choices=var_choices, selected = var_choices[1]),<br> plotOutput(<span style="background-color:#ffb700">ns("hist_plot")</span>)<br> )<br>}</code> - Initialize the namespace for `id` using .bg-gold[`NS()`] function - Need to refer to any controls/plots with ids wrapped in `ns()`, such as .bg-gold[`ns("x_var")`] or .bg-gold[`ns("hist_plot")`] --- # Server Module <code class ='r hljs remark-code'>select_hist_server <- function(id, data) {<br> <span style="background-color:#ffb700">moduleServer</span>(id, function(input, output, session) {<br><br><span style="background-color:#ffff7f"> output$hist_plot <- renderPlot({</span><br><span style="background-color:#ffff7f"> #notice we don't use ns() here to refer to input objects</span><br><span style="background-color:#ffff7f"> x_var <- input$x_var</span><br><br><span style="background-color:#ffff7f"> data %>% ggplot(aes_string(x=x_var)) +</span><br><span style="background-color:#ffff7f"> geom_histogram()</span><br><span style="background-color:#ffff7f"> </span><br><span style="background-color:#ffff7f"> })</span><br> <br>})<br> <br>}</code> - .bg-gold[`moduleServer()`] encapsulates your server code (in .bg-yellow[yellow]) - be really careful with closing curly brackets and parentheses --- # Try them out Install `shiny`, `palmerpenguins`, `tidyverse` first Clone this repository: https://github.com/laderast/shiny_module_tutorial/ Open up `shiny_module_tutorial.Rproj` - Individual apps are in `module_demo_01` and `module_demo_02` --- # For More Info/Thanks! - [Mastering Shiny: Modules](https://mastering-shiny.org/scaling-modules.html) - Slides were done using `xaringan`, `xaringanExtra`, and `flair`