Reactivity in Interactive Documents

Using OJS Variables for Reactive Interactivity

Learn how to harness OJS variables to create reactive, dynamic interactive documents in Quarto Live. This tutorial covers techniques for pre-rendering data and integrating it with live, client-side interactivity using practical examples like histograms and boxplots.

Tools
Author
Affiliation
Published

March 21, 2025

Keywords

reactive programming R, reactive Python, OJS interactive

Introduction

Interactive documents built with Quarto Live can seamlessly combine pre-rendered static content with live, reactive code. By using OJS variables, you can pre-compute data during build time and then import it into live code cells that update instantly based on user inputs. This hybrid approach delivers high performance while providing dynamic interactivity.



1. What is Reactivity?

Reactivity enables your document to update automatically when data or inputs change. By pre-rendering heavy computations and exporting them as OJS variables, you can pass these values to live interactive cells—ensuring quick load times and immediate feedback.

2. Using OJS Variables in Interactive Documents

Creating Reactive Inputs with OJS

OJS blocks allow you to create interactive widgets that capture user input. For example, the following code defines a checkbox input for selecting species and a dropdown menu for choosing a measure from the iris dataset.

Source

reactivity.qmd
```{ojs}
//| echo: false
viewof selected_species = Inputs.checkbox(
  ["setosa", "versicolor", "virginica"],
  { value: ["setosa", "versicolor", "virginica"], label: "Select Iris Species:" }
)
viewof measure = Inputs.select(
  ["Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width"],
  { label: "Select Measure:" }
)
```

Output

Importing OJS Variables into R Code Cells

Once defined, these OJS variables can be imported into R code blocks using the input option, enabling live reactivity.

Source

reactivity.qmd
```{webr}
#| input:
#|   - selected_species
#|   - measure
cat("Selected Species:", selected_species, "\n")
cat("Selected Measure:", measure, "\n")
```

Output

3. Pre-Rendering Data and Importing it Live

Pre-Rendering with R

You can pre-compute data during the build phase and export it as an OJS variable. For example, the following R block pre-renders a summary of the mtcars dataset.

library(dplyr)
# Pre-compute a subset of mtcars and export as an OJS variable
mpg_data <- mtcars %>% select(mpg, hp) %>% filter(mpg < 25)
ojs_define(mpg_data)

Live Interactive Plot Using Pre-Rendered Data in Python

Next, import the pre-rendered data into a Python interactive cell to create a scatter plot.

Source
```{pyodide}
#| input:
#|   - mpg_data
import pandas as pd
import matplotlib.pyplot as plt

# Convert the pre-rendered mpg_data into a DataFrame
df = pd.DataFrame(mpg_data)
plt.figure(figsize=(8, 4))
plt.scatter(df['mpg'], df['hp'], color='darkgreen')
plt.title("MPG vs Horsepower")
plt.xlabel("Miles per Gallon")
plt.ylabel("Horsepower")
plt.show()
```
Note

This cross-engine data sharing enables you to combine static processing with live interactivity.

4. Additional Practical Examples

Interactive Histogram with Live and Pre-Rendered Data

This example demonstrates an interactive histogram using live Python code, with the bin count controlled by an OJS slider.

Source

histogram.qmd
```{webr}
#| input:
#|   - bin_count
# Live R Histogram
hist(rnorm(1000), breaks = bin_count, col = "steelblue", border = "white")
```

```{ojs}
//| echo: false
//  OJS Input for Bin Count
viewof bin_count = Inputs.range([5, 50], { value: 15, step: 1, label: "Number of Bins:" })
```

Output

Reactive Boxplot with iris Dataset

This interactive boxplot allows users to select iris species and a measure to display.

Steps:

  1. Create an R function taking reactive inputs as arguments
  2. Export the function as an OJS variable
dashboard.qmd
```{webr}
#| edit: false
#| output: false
#| define:
#|   - do_reactive_boxplot
library(ggplot2)
library(dplyr)

do_reactive_boxplot <- function(selected_species, measure) {
  # Filter the iris dataset based on selected species
  filtered_iris <- iris %>% filter(Species %in% selected_species)

  # Create an interactive boxplot using the chosen measure
  p <- ggplot(filtered_iris, aes(x = Species, y = .data[[measure]], fill = Species)) +
    geom_boxplot() +
    labs(title = paste("Boxplot of", measure, "by Species"),
         x = "Species",
         y = measure) +
    theme_minimal()

  print(p)
}
```

Next, create OJS reactive inputs for species and measure selection to invoke the exported function do_reactive_boxplot().

dashboard.qmd
```{ojs}
//| echo: false
viewof species = Inputs.checkbox(
  ["setosa", "versicolor", "virginica"],
  { value: ["setosa", "versicolor", "virginica"], label: "Select Iris Species:" }
);

viewof measures = Inputs.select(
  ["Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width"],
  { label: "Select Measure:" }
);

do_reactive_boxplot(species, measures);
```

Output

Note

As you adjust the selections in the OJS widgets, the boxplot updates automatically.

5. Best Practices for Reactive Documents

  • Separate Static from Live Code:
    Pre-render heavy computations and export them as OJS variables to keep live code lightweight.

  • Minimize Data Payload:
    Export only necessary data to ensure fast load times.

  • Test Interactivity:
    Validate that changes in OJS inputs correctly trigger updates in your interactive cells.

  • Monitor Console Logs:
    Check browser developer tools for errors or warnings during the initial load.

Further Reading

Conclusion

By leveraging OJS variables, you can blend pre-rendered data with live, reactive code to create highly dynamic interactive documents. These techniques—demonstrated through examples like interactive histograms and boxplots—allow you to optimize performance while delivering rich, real-time interactivity. Experiment with these approaches to build engaging, responsive documents with Quarto Live and WebAssembly.

Back to top

Reuse

Citation

BibTeX citation:
@online{kassambara2025,
  author = {Kassambara, Alboukadel},
  title = {Reactivity in {Interactive} {Documents}},
  date = {2025-03-21},
  url = {https://www.datanovia.com/learn/interactive/advanced/reactivity.html},
  langid = {en}
}
For attribution, please cite this work as:
Kassambara, Alboukadel. 2025. “Reactivity in Interactive Documents.” March 21, 2025. https://www.datanovia.com/learn/interactive/advanced/reactivity.html.