User interface (UI)
In this section we’ll build the user interface of a simple app.
However, before we get into the weeds of building a user interface, let’s revisit the anatomy of a Shiny app.
The user interface, that we’ll refer to as the “UI” going forward, defines and lays out the inputs of your app where users can make their selections. It also lays out the outputs.
The server function, on the other hand, calculates outputs and performs any other calculations needed for the outputs.
Example
For example, if your app features a plot the code for building that plot lives in the server function. But the setup for the user defined inputs for the plot, as well as information on where physically on the app the plot should appear, are defined in the UI.
Here is the app we’ll work with in this section and the code that builds the UI of that app.
Since this is too much code to parse, we’ll explore individual components of the UI one by one.
fluidPage()
At the outermost layer of our UI definition we begin with the fluidPage()
function.
The fluidPage()
function creates a fluid page layout consisting of rows and columns. Rows make sure that elements in them appear on the same line. Columns within these rows define how much horizontal space each element should occupy.
Fluid pages scale their components in realtime to fill all available browser width, which means you, the app developer, don’t need to worry about defining relative widths for individual app components.
As always, for more information on arguments to this function, you can view the R function help by typing ?fluidPage
in your R console or visiting the function reference page on the package website here.
Layout
Next, we define the layout of our app with sidebarLayout()
.
Shiny includes a number of options for laying out the components of an application. The default layout, the one we’re using in our example app, is a layout with a sidebar, that you can define with the sidebarLayout()
function.
This is a simple layout with a narrow sidebar for inputs and a wider main area for output.
Under the hood, Shiny implements layout features available in Bootstrap 2, which is a popular HTML/CSS framework. However the nice thing about working in Shiny is that no prior experience with Bootstrap is necessary.
To learn more about various layouts, I recommend reviewing the Application Layout Guide article at shiny.rstudio.com.
Input controls
Next we define our sidebar panel containing input controls.
This panel contains two dropdown menus created with the selectInput()
function.
Let’s take a look at one of the selectInput
widgets a little more closely.
The first argument is the
inputId
, which is the input value that the app will internally use to access the value selected by the user.The second argument is the
label
, which is the display label that the user sees.The third argument is the list of
choices
the user will choose from. In this app, these are variable names from the movies dataset.And lastly we specify a default selection from that list with
selected
.
Main Panel
The final component of our UI is mainPanel()
.
Currently the main panel contains only one component, a plot output. We’ll talk about how this plot is built later in the tutorial.
Next, let’s practice building an app UI!
Practice: Extend the UI
We’ll start with a simplified version of the app you saw in the previous exercise. In this app a selectInput()
widget is used to allow the user to select which variables should be plotted on the x
and y
axes of the scatterplot.
The selectInput()
function has the following arguments:
- an
inputId
that is used to refer to the input parameter when building the scatterplot, - a list of
choices
to pick from (which must match variable names in the data frame), - and a
selected
choice for when the app first launches.
Your turn
Modify the Shiny app code in app.R
/ shown below:
In the ui
:
- Add a new
selectInput
widget to color the points by a choice of the following variables:"title_type"
,"genre"
,"mpaa_rating"
,"critics_rating"
,"audience_rating"
. - Make the default selection
"mpaa_rating"
. - Use
"z"
as theinputId
. label
can be whatever you like.
In the server
:
- Set the color argument in
ggplot()
aesthetic mappings toinput$z
.
Complete this exercise by opening up the RStudio Project titled 1-2a Extend the UI within your RStudio Cloud Workspace
Continue editing the file you started in the Getting Started section
OR
- Download the data if you haven’t already
```{r}
# Get the data
<- "https://github.com/rstudio-education/shiny-course/raw/main/movies.RData"
file <- "movies.RData"
destfile
download.file(file, destfile)
```
- Copy the code below into an R script
# Load packages ----------------------------------------------------------------
library(shiny)
library(ggplot2)
# Load data --------------------------------------------------------------------
load("movies.RData")
# Define UI --------------------------------------------------------------------
<- fluidPage(
ui
sidebarLayout(
# Inputs: Select variables to plot
sidebarPanel(
# Select variable for y-axis
selectInput(inputId = "y",
label = "Y-axis:",
choices = c("imdb_rating", "imdb_num_votes", "critics_score", "audience_score", "runtime"),
selected = "audience_score"),
# Select variable for x-axis
selectInput(inputId = "x",
label = "X-axis:",
choices = c("imdb_rating", "imdb_num_votes", "critics_score", "audience_score", "runtime"),
selected = "critics_score"),
# Select variable for color
selectInput(inputId = "___",
label = "____",
choices = c(___),
selected = "___")
),
# Output: Show scatterplot
mainPanel(
plotOutput(outputId = "scatterplot")
)
)
)
# Define server ----------------------------------------------------------------
<- function(input, output, session) {
server
$scatterplot <- renderPlot({
outputggplot(data = movies, aes_string(x = input$x, y = input$y,
color = ___)) +
geom_point()
})
}
# Create a Shiny app object ----------------------------------------------------
shinyApp(ui = ui, server = server)
# Load packages ----------------------------------------------------------------
library(shiny)
library(ggplot2)
# Load data --------------------------------------------------------------------
load("movies.RData")
# Define UI --------------------------------------------------------------------
<- fluidPage(
ui
sidebarLayout(
# Inputs: Select variables to plot
sidebarPanel(
# Select variable for y-axis
selectInput(inputId = "y",
label = "Y-axis:",
choices = c("imdb_rating", "imdb_num_votes", "critics_score", "audience_score", "runtime"),
selected = "audience_score"),
# Select variable for x-axis
selectInput(inputId = "x",
label = "X-axis:",
choices = c("imdb_rating", "imdb_num_votes", "critics_score", "audience_score", "runtime"),
selected = "critics_score"),
# Select variable for color
selectInput(inputId = "z",
label = "Color by:",
choices = c("title_type", "genre", "mpaa_rating", "critics_rating", "audience_rating"),
selected = "mpaa_rating")
),
# Output: Show scatterplot
mainPanel(
plotOutput(outputId = "scatterplot")
)
)
)
# Define server ----------------------------------------------------------------
<- function(input, output, session) {
server
$scatterplot <- renderPlot({
outputggplot(data = movies, aes_string(x = input$x, y = input$y,
color = input$z)) +
geom_point()
})
}
# Create a Shiny app object ----------------------------------------------------
shinyApp(ui = ui, server = server)
Practice: Extend the UI further
The potential variables the user can select for the x
and y
axes and color
currently appear in the UI of the app the same way that they are spelled in the data frame header. However we might want to label them in a way that is more human readable. We can achieve this using named vectors for the choices
argument, in the format of "Human readable label" = "variable_name"
.
Your turn
Fill in the blanks in the code below with human readable labels for
x
andy
inputs.Re-create the
selectInput
widget for color,z
, with options"title_type"
,"genre"
,"mpaa_rating"
,"critics_rating"
, and"audience_rating"
, default selection"mpaa_rating"
just like in the previous exercise, but this time use human readable labels as well.
Complete this exercise by opening up the RStudio Project titled 1-2b Extend the UI further within your Posit Cloud Workspace
- Continue editing the code you’ve created with the code below
# Load packages ----------------------------------------------------------------
library(shiny)
library(ggplot2)
# Load data --------------------------------------------------------------------
load("movies.RData")
# Define UI --------------------------------------------------------------------
<- fluidPage(
ui
sidebarLayout(
# Inputs: Select variables to plot
sidebarPanel(
# Select variable for y-axis
selectInput(inputId = "y",
label = "Y-axis:",
choices = c(___ = "imdb_rating",
___ = "imdb_num_votes",
___ = "critics_score",
___ = "audience_score",
___ = "runtime"),
selected = "audience_score"),
# Select variable for x-axis
selectInput(inputId = "x",
label = "X-axis:",
choices = c(___ = "imdb_rating",
___ = "imdb_num_votes",
___ = "critics_score",
___ = "audience_score",
___ = "runtime"),
selected = "critics_score"),
# Select variable for color
selectInput(inputId = "z",
label = "Color:",
choices = ___,
selected = ___)
),
# Output: Show scatterplot
mainPanel(
plotOutput(outputId = "scatterplot")
)
)
)
# Define server ----------------------------------------------------------------
<- function(input, output, session) {
server
$scatterplot <- renderPlot({
outputggplot(data = movies, aes_string(x = input$x, y = input$y,
color = input$z)) +
geom_point()
})
}
# Create a Shiny app object ----------------------------------------------------
shinyApp(ui = ui, server = server)
# Load packages ----------------------------------------------------------------
library(shiny)
library(ggplot2)
# Load data --------------------------------------------------------------------
load("movies.RData")
# Define UI --------------------------------------------------------------------
<- fluidPage(
ui
sidebarLayout(
# Inputs: Select variables to plot
sidebarPanel(
# Select variable for y-axis
selectInput(inputId = "y",
label = "Y-axis:",
choices = c("IMDB rating" = "imdb_rating",
"IMDB number of votes" = "imdb_num_votes",
"Critics score" = "critics_score",
"Audience score" = "audience_score",
"Runtime" = "runtime"),
selected = "audience_score"),
# Select variable for x-axis
selectInput(inputId = "x",
label = "X-axis:",
choices = c(
"IMDB rating" = "imdb_rating",
"IMDB number of votes" = "imdb_num_votes",
"Critics score" = "critics_score",
"Audience score" = "audience_score",
"Runtime" = "runtime"),
selected = "critics_score"),
# Select variable for color
# Select variable for color
selectInput(inputId = "z",
label = "Color by:",
choices = c(
"Title type" = "title_type",
"Genre" = "genre",
"MPAA rating" = "mpaa_rating",
"Critics rating" = "critics_rating",
"Audience rating" = "audience_rating"),
selected = "mpaa_rating")
),
# Output: Show scatterplot
mainPanel(
plotOutput(outputId = "scatterplot")
)
)
)
# Define server ----------------------------------------------------------------
<- function(input, output, session) {
server
$scatterplot <- renderPlot({
outputggplot(data = movies, aes_string(x = input$x, y = input$y,
color = input$z)) +
geom_point()
})
}
# Create a Shiny app object ----------------------------------------------------
shinyApp(ui = ui, server = server)