The shiny R package includes the conditionalPanel function to show / hide a panel depending on a javascript expression. Today I learned how to use a conditionalPanel within a shiny module.
It encapsulates the ui and server elements in separate functions, that together constitute the mod_histogram module.
library(shiny)mod_histogram_ui <-function(id){1 ns <-NS(id)fluidPage(sidebarPanel(selectInput(ns("plotType"), "Plot Type",c(Scatter ="scatter", Histogram ="hist") ),# Only show this panel if the plot type is a histogramconditionalPanel(condition ="input.plotType == 'hist'",2ns = ns,selectInput(ns("breaks"), "Breaks",c("Sturges", "Scott", "Freedman-Diaconis", "[Custom]"="custom") ),# Only show this panel if Custom is selectedconditionalPanel(condition ="input.breaks == 'custom'",ns = ns,sliderInput(ns("breakCount"), "Break Count", min =1,max =100, value =10) ) ) ),mainPanel(plotOutput(ns("plot")) ) )}mod_histogram_server <-function(id, df, labels, interactive =FALSE){moduleServer( id, function(input, output, session){ x <-rnorm(1000) y <-rnorm(1000) output$plot <-renderPlot({if (input$plotType =="scatter") {plot(x, y) } else { breaks <- input$breaksif (breaks =="custom") { breaks <- input$breakCount }hist(x, breaks = breaks) } }) })}histogramApp <-function() { ui <-mod_histogram_ui("histogram_1") server <-function(input, output, session) {mod_histogram_server("histogram_1") }shinyApp(ui, server)}
1
The ns object defined in the UI part of the module takes care of managing the module’s namespace.
2
The ns namespace is passed as an argument to each conditionalPanel call. It automatically modifies the condition javascript expression, so we do not need to include the module’s id ourselves (e.g. via paste or sprintf, as is sometimes advised on Stack Overflow).
To see a minial shiny app, call the histogramApp() function:
histogramApp()
Reproducibility
Session Information
sessioninfo::session_info("attached")
─ Session info ───────────────────────────────────────────────────────────────
setting value
version R version 4.3.2 (2023-10-31)
os Debian GNU/Linux 12 (bookworm)
system x86_64, linux-gnu
ui X11
language (EN)
collate en_US.UTF-8
ctype en_US.UTF-8
tz America/Los_Angeles
date 2024-04-07
pandoc 3.1.1 @ /usr/lib/rstudio/resources/app/bin/quarto/bin/tools/ (via rmarkdown)
─ Packages ───────────────────────────────────────────────────────────────────
! package * version date (UTC) lib source
P shiny * 1.7.5 2023-08-12 [?] CRAN (R 4.3.1)
[1] /home/sandmann/repositories/blog/renv/library/R-4.3/x86_64-pc-linux-gnu
[2] /home/sandmann/.cache/R/renv/sandbox/R-4.3/x86_64-pc-linux-gnu/9a444a72
P ── Loaded and on-disk path mismatch.
──────────────────────────────────────────────────────────────────────────────
---title: "Conditional panels within shiny modules"author: "Thomas Sandmann"date: "2024-04-07"freeze: truecategories: [R, shiny, TIL]editor: markdown: wrap: 72format: html: toc: true toc-depth: 4 code-tools: source: true toggle: false caption: noneeditor_options: chunk_output_type: console---## tl;drThe [shiny R package](https://cran.r-project.org/package=shiny)includes the[conditionalPanel](https://rstudio.github.io/shiny/reference/conditionalPanel.html)function to show / hide a panel depending on a javascript expression. Today Ilearned how to use a `conditionalPanel` within a[shiny module](https://mastering-shiny.org/scaling-modules.html).## A shiny module with several conditional selectorsThe following example [^1] expands the example shown on the [conditionalPanel help page](https://rstudio.github.io/shiny/reference/conditionalPanel.html). [^1]: Also available in [this gist](https://gist.github.com/tomsing1/884f32a3f40abd9a937dab0c54d23fda)It encapsulates the ui and server elements in separate functions, that togetherconstitute the `mod_histogram` module. ```{r}library(shiny)mod_histogram_ui <-function(id){ ns <-NS(id) # <1>fluidPage(sidebarPanel(selectInput(ns("plotType"), "Plot Type",c(Scatter ="scatter", Histogram ="hist") ),# Only show this panel if the plot type is a histogramconditionalPanel(condition ="input.plotType == 'hist'",ns = ns, # <2>selectInput(ns("breaks"), "Breaks",c("Sturges", "Scott", "Freedman-Diaconis", "[Custom]"="custom") ),# Only show this panel if Custom is selectedconditionalPanel(condition ="input.breaks == 'custom'",ns = ns,sliderInput(ns("breakCount"), "Break Count", min =1,max =100, value =10) ) ) ),mainPanel(plotOutput(ns("plot")) ) )}mod_histogram_server <-function(id, df, labels, interactive =FALSE){moduleServer( id, function(input, output, session){ x <-rnorm(1000) y <-rnorm(1000) output$plot <-renderPlot({if (input$plotType =="scatter") {plot(x, y) } else { breaks <- input$breaksif (breaks =="custom") { breaks <- input$breakCount }hist(x, breaks = breaks) } }) })}histogramApp <-function() { ui <-mod_histogram_ui("histogram_1") server <-function(input, output, session) {mod_histogram_server("histogram_1") }shinyApp(ui, server)}```1. The `ns` object defined in the UI part of the module takes care of managing the module's namespace.2. The `ns` namespace is passed as an argument to each `conditionalPanel` call. It automatically modifies the `condition` javascript expression, so we do _not_ need to include the module's id ourselves (e.g. via `paste` or `sprintf`, as is sometimes advised on Stack Overflow).To see a minial shiny app, call the `histogramApp()` function:```{r}#| eval: falsehistogramApp()```## Reproducibility<details><summary>Session Information</summary>```{r}sessioninfo::session_info("attached")```</details>