19.4 Shiny widgets

Shiny widgets enable you to create re-usable Shiny components that are included within an R Markdown document using a single function call. Shiny widgets can also be invoked directly from the console (useful during authoring) and show their output within the RStudio Viewer pane or an external web browser.

19.4.1 The shinyApp() function

At their core, Shiny widgets are mini-applications created using the shinyApp() function. Rather than creating a ui.R and server.R (or app.R) as you would for a typical Shiny application, you pass the UI and server definitions to the shinyApp() function as arguments. We have given an example in Section 19.3.1.

The simplest type of Shiny widget is just an R function that returns a shinyApp().

19.4.2 Example: k-Means clustering

The rmdexamples package (https://github.com/rstudio/rmdexamples) includes an example of a Shiny widget implemented in this fashion. The kmeans_cluster() function takes a single dataset argument and returns a Shiny widget to show the result of k-Means clustering. You can use it within an R Markdown document like this:

```{r, echo = FALSE}
library(rmdexamples)
kmeans_cluster(iris)
```

Figure 19.5 shows what the widget looks like inside a running document.

A Shiny widget to apply k-Means clustering on a dataset.

FIGURE 19.5: A Shiny widget to apply k-Means clustering on a dataset.

Below is the source code of the kmeans_cluster() function:

kmeans_cluster = function(dataset) {

  library(shiny)  
  vars = names(dataset)

  shinyApp(
    ui = fluidPage(
      fluidRow(style = "padding-bottom: 20px;",
        column(4, selectInput('xcol', 'X Variable', vars)),
        column(4, selectInput('ycol', 'Y Variable', vars,
                              selected = vars[2])),
        column(4, numericInput('clusters', 'Cluster count', 3,
                               min = 1, max = 9))
      ),
      fluidRow(
        plotOutput('kmeans', height = "400px")  
      )
    ),

    server = function(input, output, session) {

      # Combine the selected variables into a new data frame
      selectedData = reactive({
        dataset[, c(input$xcol, input$ycol)]
      })

      clusters = reactive({
        kmeans(selectedData(), input$clusters)
      })

      output$kmeans = renderPlot(height = 400, {
        res = clusters()
        par(mar = c(5.1, 4.1, 0, 1))
        plot(selectedData(),
             col = res$cluster, pch = 20, cex = 3)
        points(res$centers, pch = 4, cex = 4, lwd = 4)
      })
    },

    options = list(height = 500)
  )
}

19.4.3 Widget size and layout

Shiny widgets may be embedded in various places including standard full width pages, smaller columns within pages, and even HTML5 presentations. For the widget size and layout to work well in all of these contexts, we recommend that the total height of the widget is no larger than 500 pixels. This is not a hard and fast rule, but HTML5 slides can typically only display content less than 500px in height, so if you want your widget to be usable within presentations, this is a good guideline to follow.

You can also add an explicit height argument to the function that creates the widget (default to 500 so it works well within slides).