By: Joe Cheng
Shiny was originally conceived as a medium for interactively communicating ideas and results. As the author of a Shiny app, you perform your analysis or build your models, and then write a Shiny app to let other people–especially those without R expertise–explore your findings or data.
Shiny Gadgets are different. Gadgets are interactive tools that enhance your R programming experience.
Where a Shiny app represents the output of an analysis, Shiny Gadgets are designed to be used in the course of analysis.
Where Shiny apps are designed to be used by end users, Shiny Gadgets are intended to be used by R users.
Where Shiny apps are ultimately intended to be deployed on servers (like Shiny Server or ShinyApps.io) and accessed via a web browser, Shiny Gadgets are only ever intended to be invoked from code (in the R console or from an R script) or from within RStudio.
Shiny Gadgets can be registered with RStudio as Addins, which makes them easy to discover and use in the GUI.
Shiny Gadgets could be created for most any task you might do during data loading, cleaning, manipulation, and visualization. Here are just a few ideas:
- An easy-to-use UI for downloading data from a complicated API and turning it into a data frame
- A tool to preview regular expressions for find/replace (
- Visual selection tools for subsetting or outlier exclusion
Writing Shiny Gadgets
If you know how to write Shiny apps, you already know almost everything you need to write Shiny Gadgets, too. You still define UI, and provide a function for the server logic. You use the same reactive programming paradigm.
The main difference is how your UI and server logic is packaged. While Shiny apps generally have their own app directory (containing either ui.R/server.R files or a single app.R file), Shiny Gadgets are defined right inside a regular function.
Here’s a skeleton:
As you can see, the
server variables are very recognizably Shiny constructs, but they’re created right inside the gadget function. The fact that they’re created inside the gadget function is important, because it means they can directly access the function’s arguments (
inputValue2), and the return value from
runGadget can be the return value for the function.
You might also have noticed that the
ui definition uses
miniContentPanel instead of the more familiar
sidebarLayout, etc. That’s because gadgets default to running in the RStudio Viewer pane, which is much smaller than a typical browser window. Given the smaller real estate, it makes less sense to use the usual layout constructs in Shiny, so the
miniUI package provides different layout functions that make better use of the available space. We’ll go into more detail about this below.
gadgetTitleBar call adds a bar across the top of your app that includes the title, plus Cancel and Done buttons. You handle the Done button as shown in the code above, but Cancel is automatically implemented by the
runGadget call by stopping the app with a
"User cancel" error. While this default behavior should be appropriate for almost all gadgets, if you prefer a different behavior for the Cancel button, call
runGadget(ui, server, stopOnCancel = FALSE) and handle
input$cancel yourself. For example, add a block like this to the server function to return
NULL instead of erroring:
First, let’s take a look at an actual working example. This gadget takes a data frame and the names of two dimensions as input. It uses ggplot2 to render the data as a scatter plot. The user can click and drag to select points, and hit “Done” to return the relevant observations.
Try sourcing this code in your R session:
ggbrush(mtcars, "hp", "mpg") in the R console. You should see something like this:
Click and drag on the plot, then click the Done button. You’ll see the selection you made printed to the console in data frame form.
Hint: If you ever run a gadget (or indeed, any R console command) but forget to save the result to a variable, don’t worry! R always saves the result of the most recently run top-level expression in the
Designing Gadget UI
While technically, any kind of Shiny UI could be used for a Shiny Gadget, we’ve created a
miniUI package that we think is particularly well suited for Gadget use. We recommend that you start with
miniUI based UI for your gadget, unless you have a specific reason not to.
Learn more about creating gadget UI with
miniUI in the article Designing Gadget UI.
runGadget call has a
viewer parameter that can be used to control how the gadget will be displayed in RStudio. The shinygadgets package includes functionality for rendering:
In a pane
The example above launched a gadget in RStudio’s Viewer pane. This is the default behavior.
If your gadget has a minimum height below which it doesn’t work properly or looks silly, you can request that Viewer pane be resized to at least that height before displaying:
In a dialog
If you have a larger gadget, you can ask RStudio to show a gadget in a modal “dialog” that floats over the top of the other panes:
To opt into this behavior, change the
runGadget call to:
You can pass
height arguments to
dialogViewer to indicate your preferred size (though RStudio is free to render the gadget at a smaller size if the RStudio main window itself is too small to accommodate your size preference).
In a web browser
Finally, if you prefer to launch the gadget in the system’s external browser (like Chrome or Firefox) you can do so by using
As an RStudio Addin
After you’ve created a gadget, you can register it as an RStudio Addin, making available from a drop-down menu in RStudio:
To learn how to do this, see the RStudio Addin documentation.
For more on this topic, see the following resources:
[Shiny Gadgets: Interactive Tools](https://resources.rstudio.com/webinars/shiny-gadgets
If you have questions about this article or would like to discuss ideas presented here, please post on RStudio Community. Our developers monitor these forums and answer questions periodically. See help for more help with all things Shiny.