This is a special UI input widget designed to launch a download window from your Shiny app.
downloadButton() is a special case of an actionButton() with specialized server syntax. These are different from the other inputs we’ve used this far as they are primarily used to trigger an action rather than return a value.
Rahter than using an observe() or render*(), this widgte is paired with the special downloadHandler() which uses the latter’s syntax in our server function.
downloadHandler()
Specifically, within our server definition we attach the downloadHandler() to the button’s id via output, e.g.
output$download_btn =downloadHandler(...)
The handler then defines a filename function for generating a default filename and a content function for writing the download file’s content to a temporary file, which is then served by Shiny for downloading by the user.
For both observers and reactive expressions Shiny will automatically determine reactive dependencies for you - in some cases this is not what we want.
To explicitly control the dependencies of reactive expressions, render functions, and observers we can modify them using bindEvent() where the dependencies are explicitly listed
Similar effects can be achieved via observeEvent() / eventReactive() but these have been soft deprecated as of Shiny 1.6.
Modal dialogs
These are a popup window element that allow us to present important messages (e.g. warnings or errors) or other UI elements in a way that does not permanently clutter up the main UI of an app.
The modal dialog consists of a number of Shiny UI elements (static or dynamic) and only displays when it is triggered (usually by something like an action button or link).
They differ from other UI elements we’ve seen so far as they are usually defined within the app’s server function and not the ui.
This widget behaves a bit differently than the others we have seen - before the file is uploaded, the input will return NULL. After file(s) are uploaded the input returns a data frame with one row per file and the following columns:
name - the original filename (from the client’s system)
size - file size in bytes
type - file mime type, usually determined by the file extension
datapath - location of the temporary file on the server
Given this data frame, your app’s server code is responsible for the processing and reading in the uploaded file(s).
input$upload will default to NULL when the app is loaded, using req(input$upload) for downstream consumers is a good idea
Files in datapath are temporary and should be treated as ephemeral
additional uploads can result in the previous files being deleted
type is at best a guess - validate uploaded files and write defensive code
The accept argument helps to limit file types but cannot prevent bad uploads
Your turn - Exercise 05
Starting with the code in exercises/ex05.R replace the preloading of the weather data (d) with a reactive() version that is populated via a fileInput() widget.
You should then be able to get the same app behavior as before once data/weather.csv is uploaded. You can also check that your app works with the data/portland.csv dataset as well.
Hint - remember that anywhere that uses either d will now need to use d() instead.
12:00
Modern UIs with bslib
Shiny & bootstrap
Much of the interface provided by Shiny is based on the html elements, styling, and javascript provided by the Bootstrap library.
Knowing the specifics of html (and Bootstrap specifically) are not needed for working with Shiny - but understanding some of its conventions goes a long way to helping you customize the elements of your app (via custom CSS and other tools).
This is not the only place that Bootstrap shows up in the R ecosystem - both RMarkdown and Quarto html documents use Bootstrap for styling as well.
bslib
The bslib R package provides a modern UI toolkit for Shiny, R Markdown, and Quarto based on Bootstrap.
It provides,
Custom theming of Shiny apps and R Markdown documents
Switch between different versions of Bootstrap
Modern UI components like cards, value boxes, sidebars, and more.
This last set of features is what we will focus on now, with more on the first two after the break.
Cards
Cards are a UI element that you will recognize from many modern websites. They are rectangular containers with borders and padding that are used to group related information. When utilized properly to group related information, they help users better digest, engage, and navigate through content
Cards are also super flexible and can contain multiple card_body() elements. This can be useful for creating complex layouts.
card(max_height =450,card_header("Text and a map!",class ="bg-dark" ),card_body(max_height =200, class ="p-0", leaflet::leaflet() |> leaflet::addTiles() ),card_body( lorem::ipsum(paragraphs =1, sentences =3 ) ))
Value boxes
Value boxes are the other major UI component provided by bslib. They are a simple way to display a value and a label in a styled box. They are often used to display key metrics in a dashboard.