Dashboards with Observable JS
Introduction
Quarto includes native support for Observable JS, a set of enhancements to vanilla JavaScript created by Mike Bostock (also the author of D3). Observable JS is distinguished by its reactive runtime, which is especially well suited for interactive data exploration and analysis.
The creators of Observable JS (Observable, Inc.) run a hosted service at https://observablehq.com/ where you can create and publish notebooks. Additionally, you can use Observable JS (“OJS”) in standalone documents and websites via its core libraries. Quarto uses these libraries along with a compiler that is run at render time to enable the use of OJS within Quarto documents.
Walkthrough
Quarto Dashboards are a great way to present interactive OJS visualizations. Below we’ll provide a complete example which will give you a high level view of the basics. If you want to learn more, please see the complete documentation on Using OJS with Quarto.
This example covers many of the techniques you’ll use when creating dashboards with OJS, including reactive calculations and more advanced layout constructs like sidebars and tabsets. Here is the interactive document we’ll be building:
The source code for this dashboard is below. Note that we add the
//| output: false
option to the first cell: this is to designate the cell as having only intermediate computations (so it should not be turned into a card in the dashboard layout).
Click on the numbers on the far right for additional explanation of syntax and mechanics)
---
"Palmer Penguins"
title: "Cobblepot Analytics"
author: format: dashboard
---
```{ojs}//| output: false
= FileAttachment("penguins.csv")
data
.csv({ typed: true })
= data.filter(function(penguin) {
filtered return bill_length_min < penguin.bill_length_mm &&
;
islands.includes(penguin.island)
})
```
# {.sidebar}
![](images/penguins.png){width="80%"}
```{ojs}= Inputs.range(
viewof bill_length_min 32, 50],
[35, step: 1, label: "Bill length (min):"}
{value:
)= Inputs.checkbox(
viewof islands "Torgersen", "Biscoe", "Dream"],
["Torgersen", "Biscoe", "Dream"],
{ value: ["Islands:"
label:
}
)
```
# Plot
```{ojs}
Plot.rectY(filtered,
Plot.binX("count"},
{y: "body_mass_g", fill: "species", thresholds: 20}
{x:
))
.plot({
facet: {
data: filtered,"sex",
x: "species",
y: 80
marginRight:
},
marks: [
Plot.frame(),
]
}
)
```
# Data
```{ojs}
Inputs.table(filtered) ```
- 1
-
We set
output: false
to indicate that this cell includes only intermediate calculations and should not have its contents printed. - 2
- We read the raw penguins dataset from a CSV when the page loads.
- 3
-
filtered
is a value that is automatically recomputed when variables declared withviewof
change (in this casebill_length_min
andislands
). - 4
-
Create global sidebars by adding the
.sidebar
class to a level 1 header. Sidebars can include code cells as well as images, narrative, and links. - 5
-
Here we define our inputs using
viewof
so that thefiltered
dataset is automatically recomputed when they change. - 6
-
Level 1 headings (here
# Plots
and# Data
) create pages within the dashboard. - 7
-
The plot is automatically redrawn whenever the
filtered
dataset changes. - 8
-
The tabular data display is automatically refreshed whenever the
filtered
dataset changes.
Learning More
To learn more about using OJS with Quarto, see the following articles:
Input describes various ways to layout inputs (sidebars, input panels, attaching inputs directly to cards, etc.).
Using OJS provides an introduction and overview of other topics.
OJS Libraries covers using standard libraries and external JavaScript libraries.
OJS Data Sources outlines the various ways to read and pre-process data.
OJS Cells goes into more depth on cell execution, output, and layout.
OJS Code Reuse delves into ways to re-use OJS code across multiple documents.