robservable in Shiny applications

Julien Barnier, Kenton Russell

2022-06-28

Basic usage

robservable can be used inside a Shiny app the same way as any htmlwidget. Widgets are placed in the ui with robservableOutput, and are rendered in server with renderRobservable.

You will find the following basic example in examples/01_shiny_basic.R.

## Basic robservable Shiny app

library(shiny)
library(robservable)

data("USPersonalExpenditure")

ui <- fluidPage(
    titlePanel("robservable basic Shiny app"),
    sidebarLayout(
        sidebarPanel(
            selectInput(
                "year",
                label = "Year",
                choices = colnames(USPersonalExpenditure)
            )
        ),
        mainPanel(
           robservableOutput("chart", width = 600)
        )
    )
)


server <- function(input, output) {

    df <- reactive({
        data.frame(
            name = rownames(USPersonalExpenditure),
            value = USPersonalExpenditure[, input$year]
        )
    })

    output$chart <- renderRobservable({
        robservable(
            "@d3/horizontal-bar-chart",
            include = "chart",
            input = list(
                data = df(),
                margin = list(top = 20, right = 20, bottom = 30, left = 130)
            ),
            width = 600
        )
    })
}

shinyApp(ui = ui, server = server)

As for any robservable usage, we have to ensure that the data passed to the widget is in the same format as the one used in the notebook (same shape, same column names).

Another example displaying a multi-line chart with some interactivity can be found in examples/02_shiny_simple.R.

Animated transitions

When the notebook is designed appropriately, charts can be updated with animated transitions instead of being recreated from scratch. You will find an example of these in examples/03_shiny_updatable.R, and the associated notebook.

For more examples, the following notebooks provide charts that are updatable with animated transitions and who follow the pattern given at the end of the Learn D3 animation notebook :

Observers – using robservable widgets as inputs

You can add observers to an robservable widget and use its associated cell values as inputs inside your Shiny app.

This can allow, for example, to use any input defined in the famous Inputs notebook to be used as an input in a Shiny app.

In the example in examples/04_shiny_observers.R, we use worldMapCoordinates as an input to update a leaflet map.

To add an observer to an included cell, you must add the cell names to the observers argument.

robservable(
    "@jashkenas/inputs",
    include = c("worldMapCoordinates", "viewof worldMap1"),
    hide = "worldMapCoordinates",
    observers = "worldMap1"
)

The cell values will then be accessible via the Shiny input object by prefixing the observer name with the robservable Shiny id. So, for example, you can use the previous robservable instance as an robservableOutput with id map_input.

## In ui
robservableOutput("map_input")

## In server
output$map_input <- renderRobservable({
    robservable(
        "@jashkenas/inputs",
        include = c("worldMapCoordinates", "viewof worldMap1"),
        hide = "worldMapCoordinates",
        observers = "worldMap1"
    )
})

Then the values will be accessible in input$map_input_worldMap1.

You can use a named list as observers argument to specify custom Shiny input names, but you will still have to add the id (map_input in this example) prefix. So with the following, values will be accessible in input$map_input_point.

robservable(
    "@jashkenas/inputs",
    include = c("worldMapCoordinates", "viewof worldMap1"),
    hide = "worldMapCoordinates",
    observers = list(point = "worldMap1")
)

Proxy usage

robservable is built to update rather than completely re-render any renderRobservable calls after initial creation. However the updating renderRobservable command might need to contain all of the arguments used in the original render. robservable provides proxy methods to ease manipulation of the widget once it has been rendered. Currently, the package supports the following proxy methods:

You can find examples of these proxy methods usage in several sample applications :