The ui defines the look and feel of the app - the user interface
Use it to define where output "lives"
It also defines the inputs for the server, where functions are actually
evaluated.
In this case - we have defined a sliderInput, which we're calling "bins".
It will take on values from 1 to 50, and will start at 30.
Access the specific value the user selects within the server, through input$bins.
The server function takes the input from the UI and puts it in normal R code.
In this case, we're creating one output object, called distPlot. The result is then called through the ui on line 30
Try removing lines 39-44, and replacing it with print(input$bins)
Feels like it should work, but it doesn't. Any ideas why?
Let's say instead of a slider, we want 5 options: 1, 5, 20, 50, or 100
We can change the input from a slider (representing continuous intervals) to radio buttons, representing discrete choices.
Just change sliderInput to radioButtons, and put in the appropriate choices. You can also add a selected argument for which it defaults to.
Let's say instead of a slider, we want 5 options: 1, 5, 20, 50, or 100
We can change the input from a slider (representing continuous intervals) to radio buttons, representing discrete choices.
Just change sliderInput to radioButtons, and put in the appropriate choices. You can also add a selected argument for which it defaults to.
05:00
My recommendation: Use one of the following:
DT::datatablereactable::reactableLet's build a table to go below our distribution(s) that shows mean, sd, min, and max of the corresponding distribution(s)
You'll need to create a new output object in the server, and tell the ui where it should be rendered
Use renderDataTable in the server and dataTableOutput in the ui or renderReactable and reactableOutput
If you want to use {dplyr}, as I would, then you have to deal with NSE. In this case it's not that big of a deal though. Just use !!sym(input$var), where sym transforms a string to a symbol.
[demo]
You might want to have a navbar at the top of the page, which you can create with navbarPage().
Create each page with tabPanel()
Each tabPanel needs to include everything, including the sidebarPanel() (if present), could include tabsetPanel(), mainPanel(), etc.
Move your title so it's navbarPage("App title", or the rest of the pages won't look right
You might want to have a navbar at the top of the page, which you can create with navbarPage().
Create each page with tabPanel()
Each tabPanel needs to include everything, including the sidebarPanel() (if present), could include tabsetPanel(), mainPanel(), etc.
Move your title so it's navbarPage("App title", or the rest of the pages won't look right
inputId's across pages - it won't work.Shiny is super customizable - just scratched the surface today
Mastering Shiny should be your guide for going deeper
Great for building interactive plots, but you can use it for all sorts of other things too (including text and tables)
Apps get complicated quickly
library(shiny)library(shinydashboard)ui <- dashboardPage( dashboardHeader(title = "Basic dashboard"), dashboardSidebar(), dashboardBody( # Boxes need to be put in a row (or column) fluidRow( box(plotOutput("plot1", height = 250)), box( title = "Controls", sliderInput("slider", "Number of observations:", 1, 100, 50) ) ) ))Probably the defining characteristic of the dashboard
sidebarMenu with menuItemssidebarMenu( menuItem("Histogram", tabName = "histo", icon = icon("chart-bar")), menuItem("Bin Counts", tabName = "bins", icon = icon("table")))
You can also do things like put the slider in the sidebarMenu
[demo]
Use the forcats::gss_cat dataset
Plots on one page
tvhours on y-axisTable on another page
Select the variable for x-axis on the sidebar
Variable selection should produce table with means by the variable
[walkthrough]
There's lots of extensions for shiny, and quite a few (but not as many) for shinydashboard
Consider themeing shiny apps with {shinythemes} and dashboards with {dashboardthemes}
Consider themeing figures to match your shiny theme with {thematic}
input is a basically a list object that contains objects from the uiui <- fluidPage( numericInput("count", label = "Number of values", value = 100))
After writing this code, input$count will be a available in the server, and the value it takes will depend on the browser input (starting at 100)
input is a basically a list object that contains objects from the uiui <- fluidPage( numericInput("count", label = "Number of values", value = 100))
After writing this code, input$count will be a available in the server, and the value it takes will depend on the browser input (starting at 100)
These are read-only, and cannot be modified
It must be in a reactive context, or it won't work.
That's why this results in an error
server <- function(input, output, session) { print(paste0("The value of input$count is ", input$count))}shinyApp(ui, server)# > Error in .getReactiveEnvironment()$currentContext() : # > Operation not allowed without an active reactive context. # > (You tried to do something that can only be done from inside a reactive expression or observer.)From Mastering Shiny
Try this app. Type the letters in one at a time. Notice how it updates.
ui <- fluidPage( textInput("name", "What's your name?"), textOutput("greeting"))server <- function(input, output, session) { output$greeting <- renderText({ paste0("Hello ", input$name, "!") })}Notice you don't have to "run" the code each time the input updates
Your app provides instructions to R. Shiny decides when it actually runs the code.
Normal R code is imperative programming - you decide when it's run. Declarative programming means you provide instructions, but don't actually run it.
Notice you don't have to "run" the code each time the input updates
Your app provides instructions to R. Shiny decides when it actually runs the code.
Normal R code is imperative programming - you decide when it's run. Declarative programming means you provide instructions, but don't actually run it.
you describe your overall goals, and the software figures out how to achieve them
(from Hadley)
image from Mastering Shiny
Normally, you understand R code by running it top to bottom
This doesn't work with shiny
Instead, we think through reactive graphs

library(shiny)library(reactlog)reactlog_enable()ui <- fluidPage( textInput("name", "What's your name?"), textOutput("greeting"))server <- function(input, output, session) { output$greeting <- renderText({ paste0("Hello ", input$name, "!") })}shinyApp(ui, server)# close app, thenreactlogShow()Shiny is super customizable - almost limitless (see more examples here)
shinydashboard provides, basically, an alternative layout
Really helpful and fun way to build data tools for practitioners
Takes some practice, but basically allows you to write normal R code, and get interactive websites
Keyboard shortcuts
| ↑, ←, Pg Up, k | Go to previous slide |
| ↓, →, Pg Dn, Space, j | Go to next slide |
| Home | Go to first slide |
| End | Go to last slide |
| Number + Return | Go to specific slide |
| b / m / f | Toggle blackout / mirrored / fullscreen mode |
| c | Clone slideshow |
| p | Toggle presenter mode |
| t | Restart the presentation timer |
| ?, h | Toggle this help |
| Esc | Back to slideshow |