Shiny Exercises in R: 30 Practice Problems
Thirty practice problems on Shiny: UI elements, server logic, reactivity, inputs, outputs, modules, deployment. Solutions hidden.
library(shiny)
library(ggplot2)
library(dplyr)
library(rsconnect)
Section 1. UI basics (8 problems)
Exercise 1.1: Minimal app
Difficulty: Beginner.
Show solution
ui <- fluidPage("Hello world")
server <- function(input, output) {}
# shinyApp(ui, server)
Exercise 1.2: title + page layout
Difficulty: Beginner.
Show solution
ui <- fluidPage(titlePanel("Demo"), sidebarLayout(sidebarPanel("side"), mainPanel("main")))
Exercise 1.3: textInput
Difficulty: Beginner.
Show solution
ui <- fluidPage(textInput("name", "Name:"), textOutput("hello"))
server <- function(input, output) {
output$hello <- renderText(paste("Hello", input$name))
}
Exercise 1.4: numericInput
Difficulty: Beginner.
Show solution
ui <- fluidPage(numericInput("n", "n:", value = 10),
textOutput("sq"))
server <- function(input, output) {
output$sq <- renderText(input$n^2)
}
Exercise 1.5: sliderInput
Difficulty: Beginner.
Show solution
ui <- fluidPage(sliderInput("x", "x:", min = 0, max = 100, value = 50),
textOutput("y"))
server <- function(input, output) output$y <- renderText(input$x * 2)
Exercise 1.6: selectInput
Difficulty: Beginner.
Show solution
ui <- fluidPage(selectInput("c", "Choose:", choices = c("a","b","c")),
textOutput("o"))
server <- function(input, output) output$o <- renderText(input$c)
Exercise 1.7: actionButton
Difficulty: Intermediate.
Show solution
ui <- fluidPage(actionButton("go", "Go"), textOutput("o"))
server <- function(input, output) {
output$o <- renderText({ input$go; format(Sys.time()) })
}
Exercise 1.8: checkboxGroupInput
Difficulty: Intermediate.
Show solution
ui <- fluidPage(checkboxGroupInput("opts", "Options", c("a","b","c")),
textOutput("o"))
server <- function(input, output) output$o <- renderText(paste(input$opts, collapse = ","))
Section 2. Outputs (6 problems)
Exercise 2.1: textOutput
Difficulty: Beginner.
Show solution
ui <- fluidPage(textOutput("t"))
server <- function(input, output) output$t <- renderText("hello")
Exercise 2.2: tableOutput
Difficulty: Beginner.
Show solution
ui <- fluidPage(tableOutput("tbl"))
server <- function(input, output) output$tbl <- renderTable(head(mtcars))
Exercise 2.3: plotOutput
Difficulty: Intermediate.
Show solution
ui <- fluidPage(plotOutput("p"))
server <- function(input, output) {
output$p <- renderPlot(plot(mtcars$wt, mtcars$mpg))
}
Exercise 2.4: ggplot output
Difficulty: Intermediate.
Show solution
ui <- fluidPage(plotOutput("p"))
server <- function(input, output) {
output$p <- renderPlot(ggplot(mtcars, aes(wt, mpg)) + geom_point())
}
Exercise 2.5: dataTableOutput (DT)
Difficulty: Intermediate.
Show solution
ui <- fluidPage(DT::DTOutput("tbl"))
server <- function(input, output) output$tbl <- DT::renderDT(mtcars)
Exercise 2.6: verbatimTextOutput
Difficulty: Intermediate.
Show solution
ui <- fluidPage(verbatimTextOutput("o"))
server <- function(input, output) output$o <- renderPrint(summary(mtcars))
Section 3. Reactivity (6 problems)
Exercise 3.1: reactive expression
Difficulty: Intermediate.
Show solution
ui <- fluidPage(numericInput("n", "n:", 10), textOutput("sq"))
server <- function(input, output) {
squared <- reactive(input$n^2)
output$sq <- renderText(squared())
}
Exercise 3.2: observeEvent
Difficulty: Intermediate.
Show solution
ui <- fluidPage(actionButton("go", "Go"))
server <- function(input, output) {
observeEvent(input$go, message("clicked"))
}
Exercise 3.3: eventReactive
Difficulty: Advanced.
Show solution
ui <- fluidPage(numericInput("n", "n:", 10), actionButton("go","Go"), textOutput("o"))
server <- function(input, output) {
v <- eventReactive(input$go, input$n^2)
output$o <- renderText(v())
}
Exercise 3.4: req() to gate
Difficulty: Intermediate.
Show solution
ui <- fluidPage(textInput("name","Name:"), textOutput("o"))
server <- function(input, output) {
output$o <- renderText({
req(input$name)
paste("Hello", input$name)
})
}
Exercise 3.5: isolate
Difficulty: Advanced.
Show solution
ui <- fluidPage(numericInput("a","a:",1), actionButton("go","Go"), textOutput("o"))
server <- function(input, output) {
output$o <- renderText({ input$go; isolate(input$a) })
}
Exercise 3.6: reactiveVal
Difficulty: Advanced.
Show solution
ui <- fluidPage(actionButton("go","+1"), textOutput("o"))
server <- function(input, output) {
count <- reactiveVal(0)
observeEvent(input$go, count(count() + 1))
output$o <- renderText(count())
}
Section 4. Layout and dynamic UI (5 problems)
Exercise 4.1: tabsetPanel
Difficulty: Intermediate.
Show solution
ui <- fluidPage(tabsetPanel(tabPanel("A","panel A"), tabPanel("B","panel B")))
Exercise 4.2: navbarPage
Difficulty: Intermediate.
Show solution
ui <- navbarPage("App", tabPanel("One", "..."), tabPanel("Two", "..."))
Exercise 4.3: conditionalPanel
Difficulty: Advanced.
Show solution
ui <- fluidPage(checkboxInput("show", "show?"),
conditionalPanel("input.show == true", "secret content"))
Exercise 4.4: insertUI / removeUI
Difficulty: Advanced.
Show solution
ui <- fluidPage(actionButton("add","Add"), tags$div(id = "host"))
server <- function(input, output) {
observeEvent(input$add,
insertUI("#host", "afterBegin", textInput(paste0("t", input$add), "text")))
}
Exercise 4.5: renderUI
Difficulty: Advanced.
Show solution
ui <- fluidPage(numericInput("n","n:",3), uiOutput("dyn"))
server <- function(input, output) {
output$dyn <- renderUI({
lapply(1:input$n, function(i) textInput(paste0("t",i), paste("Field",i)))
})
}
Section 5. Modules and deployment (5 problems)
Exercise 5.1: Module UI
Difficulty: Advanced.
Show solution
counterUI <- function(id) {
ns <- NS(id)
tagList(actionButton(ns("go"), "+1"), textOutput(ns("o")))
}
Exercise 5.2: Module server
Difficulty: Advanced.
Show solution
counterServer <- function(id) moduleServer(id, function(input, output, session) {
count <- reactiveVal(0)
observeEvent(input$go, count(count()+1))
output$o <- renderText(count())
})
Exercise 5.3: Wire module
Difficulty: Advanced.
Show solution
ui <- fluidPage(counterUI("c1"))
server <- function(input, output) counterServer("c1")
Exercise 5.4: rsconnect deployment basics
Difficulty: Advanced.
Show solution
# After setting account once:
# rsconnect::deployApp("path/to/app")
Exercise 5.5: Reactive value sharing across modules
Difficulty: Advanced.
Show solution
serverA <- function(id, shared) moduleServer(id, function(input, output, session) {
observeEvent(input$go, shared(shared() + 1))
})
What to do next
- R-Markdown-Exercises (coming), reproducible reporting.
- Data-Visualization-Exercises (shipped), viz inside Shiny.