4 Outputs

Output are ways that the Shiny app can dynamically display information to the user. In the user interface (UI), you create outputs with IDs that you reference in an associated rendering function inside the server function.

Explore some different output types in the embedded app below before you read about how to set up each type.

Figure 4.1: Output Demo App. You can also access this app with shinyintro::app("output_demo")or view it in a separate tab with the showcase interface.

4.1 Text

textOutput() defaults to text inside a generic <span> or <div>, but you can use a different element with the container argument.

# in the UI function
textOutput("demo_text", container = tags$h3)

renderText() replaces the text of the linked element with its returned string.

# in the server function
output$demo_text <- renderText({
    sprintf("Plot of %s", input$y)
})

If you use verbatimTextOutput() in the UI (no change to the render function), it will show the output in a fixed-width font. This can be good for code or text you want the user to copy.

# in the UI function
verbatimTextOutput("demo_verbatim")

# in the server function
output$demo_verbatim <- renderText({
  code <-
    "ggplot(iris, aes(x = Species, y = %s, color = Species)) +
    geom_violin(show.legend = FALSE) +
    stat_summary(show.legend = FALSE)"
  
  sprintf(code, input$y)
})

4.2 Plots

plotOutput() displays plots made with the base R plotting functions (e.g., plot(), hist()) or ggplot2 functions.

# in the UI function
plotOutput("demo_plot", width = "500px", height="300px")

What is the default value for width?

What is the default value for height?

# in the server function
output$demo_plot <- renderPlot({
  ggplot(iris, aes(x = Species, y = .data[[input$y]], color = Species)) +
    geom_violin(show.legend = FALSE) +
    stat_summary(show.legend = FALSE) +
    ylab(input$y)
})

If you want to create dynamic plots that change with input, note how you need to use y = .data[[input$y]] inside aes(), instead of just y = input$y.

4.3 Images

imageOutput() takes the same arguments as plotOutput(). You can leave width and height as their defaults if you are going to set those values in the render function.

# in the UI function
imageOutput("demo_image")

renderImage() needs to return a named list with at least an src with the image path. You can also set the width and height (numeric values are in pixels), class and alt (the alt-text for screen readers).

# in the server function
output$demo_image <- renderImage({
    list(src = "images/flower.jpg",
         width = 100,
         height = 100,
         alt = "A flower")
}, deleteFile = FALSE)

The deleteFile argument is currently optional, but triggers periodic warnings that it won't be optional in the future. You should set it to TRUE if you're making a temporary file (this stops unneeded plots using memory) and FALSE if you're referencing a file you previously saved.

4.4 Tables

Display a table using tableOutput().

# in the UI function
tableOutput("demo_table")

This is paired with renderTable(), which makes a table out of any data frame it returns.

# in the server function
output$demo_table <- renderTable({
  iris %>%
    group_by(Species) %>%
    summarise(mean = mean(.data[[input$y]]),
              sd = sd(.data[[input$y]]))
})

Note how you need to use .data[[input$y]] inside dplyr::summarise(), instead of just input$y to dynamically choose which variable to summarise.

4.4.1 Data Tables

If you have a long table to show, or one that you want users to be able to sort or search, use DT::dataTableOutput() (or its synonym DTOutput()).

The basic shiny package has dataTableOutput() and renderDataTable() functions, but they can be buggy. The versions in the DT package are better and have many additional functions, so I use those.

# in the UI function
DT::dataTableOutput("demo_datatable",
                    width = "50%",
                    height = "auto")

The paired render function is renderDataTable() (or its synonym renderDT()). You can customise data tables in many ways, but we'll stick with a basic example here that limits the number of rows shown at once to 10.

# in the server function
output$demo_datatable <- DT::renderDataTable({
    iris
}, options = list(pageLength = 10))

You can use the DT synonyms to make sure you're not accidentally using the shiny versions, which don't have the same options.

4.5 Dynamic HTML

If you want to dynamically create parts of the UI, you can use uiOutput().

# in the UI function
uiOutput("demo_ui")

You can create the UI using renderUI() to return HTML created using the input functions we learned about in Section 3, the tag functions, or HTML that you write yourself (as an argument to HTML()).

# in the server function
output$demo_ui <- renderUI({
  cols <- names(iris)[1:4]
  selectInput("y", "Column to plot", cols, "Sepal.Length")
})

The function htmlOutput() is a synonym for uiOutput(), so you might see that in some code examples, but I use uiOutput() to make the connection with renderUI() clearer, since there is no renderHTML().

4.7 Exercises

Modify the demo

Clone the "output_demo" app and modify it to use a different dataset.

Pets

Add outputs and appropriate render functions to show a plot and the data from the pets questionnaire you made for the exercise in Section 3.

4.8 Your App

In the app you're developing, add relevant outputs, such as for plots or tables, and the appropriate render function for each output. You can leave the contents blank for now or add in some code to create output.