WebApps 6502

Session 1.2–R Shiny Basics

Overview

Shiny App Basics

Two parts of a Shiny app:

  • UI: User Interface
  • Server: Server logic

They come together in a single script: app.R

The app.R Script

library(shiny)

ui <- fluidPage(
  "Hello, Shiny!"
)

server <- function(input, output, session) {
}

shinyApp(ui, server)

The User Interface (ui)

The UI

library(shiny)

ui <- fluidPage(
  "Hello, Shiny!"
)

server <- function(input, output, session) {
}

shinyApp(ui, server)

fluidPage() creates a Bootstrap page

The UI

  • Bootstrap is a free front-end framework used in web development
  • It is built on HTML, CSS and JavaScript
  • There are many version of Bootstrap, the latest being version 5, but R Shiny uses version 3 by default

The UI

Under the hood, every UI function is translated to HTML.

as.character(titlePanel("Hello, Shiny!"))
[1] "<h2>Hello, Shiny!</h2>"


This HTML can have styles attached to it, either by the style attribute, or by a CSS class.

as.character(sidebarPanel())
[1] "<div class=\"col-sm-4\">\n  <form class=\"well\" role=\"complementary\"></form>\n</div>"

The UI

To let users interact with your app, you can add input controls. A basic input control has:

  • an inputId
  • a label
  • a value

The UI

For example:

numericInput(inputId = "number", 
             label = "Enter a number", 
             value = 0)


actionButton(inputId = "button", 
             label = "Click me")

Updating the UI

  • When the app runs, every user gets served the same HTML from the UI
  • When the user interacts with the UI, we want that HTML to react and update based on user input
  • That is possible because these outputs are reactive outputs
  • The server logic (which we will discuss in detail soon) uses reactive programming that updates related inputs in the UI

Updating the UI

Shiny has several functions that turn R objects into reactive outputs for your ui: the Output family of functions.

Each function creates a specific type of output, for example:

UI Function Output type
textOutput() text
tableOutput() table
plotOutput() plot
uiOutput() raw HTML

Updating the UI

Every output element needs a single argument: outputId. This is a simple string that needs to be unique.


textOutput(outputId = "text")


This textOutput tells Shiny what to display. It’s a placeholder for what is goign to be produced by the server logic.

The Server Logic

The Server

  • The server function builds an object named output and this object will contain all the code needed to display the R objects in the UI
  • This output object is list-like
  • Each R object that you want to display has its own entry in this list
  • Therefore the name of every output in your UI needs to match a definition in the server, e.g. output$text

The Server

Each entry in the output list should contain a Render function. You must use Render functions that match the Output functions:

UI Function Output type Render function
textOutput() text renderText()
tableOutput() table renderTable()
plotOutput() plot renderPlot()
uiOutput() raw HTML renderUI()

The Server

ui <- fluidPage(
  textOutput(outputId = "text")
)

server <- function(input, output, session) {
  output$text <- renderText({
  })
}

Using Inputs

  • This works the same with inputs.
  • The server can access an object named input that will contain the value of all the input objects defined in the UI.
  • This object is list-like, just like the output object. Each input value has its own entry in this list, e.g. input$number.

Combining the input and output objects, we get a simple app that displays the square of a number. 👏

library(shiny)

ui <- fluidPage(
  numericInput(inputId = "number", 
               label = "Enter a number", 
               value = 0),
               
  textOutput(outputId = "text")
)

server <- function(input, output, session) {
  output$text <- renderText({
    input$number^2
  })
}

shinyApp(ui, server)

Your Turn!

  • Create a Shiny app that displays the square of a number
  • Try entering different numbers manually
  • Try using the up and down arrows
  • Adjust the server logic to display the cube of a number
  • Try other calculations
10:00

Eager Output

An output is eager: it will update as soon as the input changes.


This eagerness is handy: you don’t need to worry about updating the output when the input changes.


But what if you want to trigger the calculation only when you want?

Adding a Reactivity Modifier

You could use an actionButton as an event:

library(shiny)

ui <- fluidPage(
  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)

Try It Yourself!

  • Add an actionButton to your app
  • Adjust the text on the button to read “Calculate”
  • Make sure it functions as intended
  • Go to the getting started lesson on control widgets
  • See if you can control the calculation with a checkbox instead of a button
  • What is wrong with this approach?

Acknowledgements