10:00
Session 2.3–Building Your App
bslib
which is a package that provides a modern UI toolkit for Shiny and R Markdown based on Bootstraplibrary(shiny)
library(bslib)
ui <- page_navbar(
theme = bs_theme(version = 5),
title = "Modular App Blueprint",
nav_panel(
title = "Numbers",
numericInput(inputId = "number",
label = "Enter a number",
value = 0),
actionButton(inputId = "button",
label = "Click me"),
textOutput(outputId = "text")
)
)
server <- function(input, output, session) {
output$text <- renderText({
input$number^2
}) |> bindEvent(input$button)
}
shinyApp(ui, server)
Use the bootswatch
argument to change the theme (other bootswatch themes:
library(shiny)
library(bslib)
ui <- page_navbar(
theme = bs_theme(version = 5, bootswatch = "minty"),
title = "Modular App Blueprint",
nav_panel(
title = "Numbers",
numericInput(inputId = "number",
label = "Enter a number",
value = 0),
actionButton(inputId = "button",
label = "Click me"),
textOutput(outputId = "text")
)
)
server <- function(input, output, session) {
output$text <- renderText({
input$number^2
}) |> bindEvent(input$button)
}
shinyApp(ui, server)
You can also customize the theme:
library(shiny)
library(bslib)
custom_theme <- bs_theme(
version = 5,
bg = "#F9F9F9",
fg = "#003f5c",
primary = "#bc5090",
secondary = "#58508d",
warning = "#ffa600",
danger = "#ff6361",
info = "#0091d5",
base_font = font_google("PT Sans")
)
ui <- page_navbar(
theme = custom_theme,
title = "Modular App Blueprint",
nav_panel(
title = "Numbers",
numericInput(inputId = "number",
label = "Enter a number",
value = 0),
actionButton(inputId = "button",
label = "Click me",
width = "100px"),
textOutput(outputId = "text")
)
)
server <- function(input, output, session) {
output$text <- renderText({
input$number^2
}) |> bindEvent(input$button)
}
shinyApp(ui, server)
bslib
10:00
shinydashboard
packageNote that the server part doesn’t run line-by-line. It’s a reactive environment that will run the code when input changes.
Code only reacts when it needs to, which is why it’s called reactive programming.
This makes it hard to test your code. And it’s hard to understand what’s going on when you’re new to Shiny!
My personal top ways ways to get more insight into what’s going on:
print()
statements to see when something is happeningbrowser()
to stop the code and inspect the environment (just as you can do within functions, because that is literally what server
is!)print()
exampleserver <- function(input, output) {
# Reactive function to fetch data
fred_indicator <- reactive({
data <- fredr(series_id = input$indicator,
observation_start = start_date,
observation_end = end_date)
print(paste("Data fetched for indicator:", input$indicator)) # Debug statement
print(head(data)) # Print first few rows of the fetched data
data
})
# Reactive function to filter data
fred_data <- reactive({
data <- fred_indicator() |>
filter(between(date, input$range[1], input$range[2]))
print(paste("Data filtered for range:", input$range[1], "to", input$range[2])) # Debug statement
data
})
# Plotting function
output$lineChart <- renderPlot({
data <- fred_data()
print("Plotting data") # Debug statement before plotting
ggplot(data, aes(x = date, y = value)) +
geom_line(color = "navyblue") +
labs(x = "", y = names(vars[which(vars == input$indicator)])) +
theme_minimal()
})
}
print()
exampleserver <- function(input, output) {
# Reactive function to fetch data
fred_indicator <- reactive({
data <- fredr(series_id = input$indicator,
observation_start = start_date,
observation_end = end_date)
print(paste("Data fetched for indicator:", input$indicator)) # Debug statement
print(head(data)) # Print first few rows of the fetched data
})
# Reactive function to filter data
fred_data <- reactive({
data <- fred_indicator() |>
filter(between(date, input$range[1], input$range[2]))
print(paste("Data filtered for range:", input$range[1], "to", input$range[2])) # Debug statement
data
})
# Plotting function
output$lineChart <- renderPlot({
data <- fred_data()
print("Plotting data") # Debug statement before plotting
ggplot(data, aes(x = date, y = value)) +
geom_line(color = "navyblue") +
labs(x = "", y = names(vars[which(vars == input$indicator)])) +
theme_minimal()
})
}
browser()
exampleserver <- function(input, output) {
# Reactive function to fetch data
fred_indicator <- reactive({
browser() # Initiate debugging here
fredr(series_id = input$indicator,
observation_start = start_date,
observation_end = end_date)
})
# Reactive function to filter data
fred_data <- reactive({
browser() # Debugging point to inspect filtered data
fred_indicator() |>
filter(between(date, input$range[1], input$range[2]))
})
# Plotting function
output$lineChart <- renderPlot({
browser() # Inspect before plotting
ggplot(fred_data(), aes(x = date, y = value)) +
geom_line(color = "navyblue") +
labs(x = "", y = names(vars[which(vars == input$indicator)])) +
theme_minimal()
})
}
print()
or browser()
statements to see when things are happening10:00
glimpse()
and View()
to verify data structures.ggplot
.data[[]]
to handle user inputs within ggplot2
aesthetics.