Skip to content

Instantly share code, notes, and snippets.

View jcheng5's full-sized avatar

Joe Cheng jcheng5

View GitHub Profile
jcheng5 / app.R
Last active June 23, 2024 18:51
Extended task example app
ui <- page_sidebar(
sidebar = sidebar(
numericInput("x", "x", 5),
jcheng5 /
Last active June 21, 2024 22:36
Accepting POST requests from Shiny

Accepting POST requests from Shiny

(This post was motivated by a talk by @jnolis at CascadiaRConf 2021)

Recent versions of Shiny have an undocumented feature for handling POST requests that are not associated with any specific Shiny session. (Note that this functionality is missing our normal level of polish; it's a fairly low-level hook that I needed to make some things possible, but doesn't make anything easy.)

In a nutshell, it works by replacing your traditional ui object with a function(req), and then marking that function with an attribute indicating that it knows how to handle both GET and POST:


Experimental function to concatenate lots of HTML dependencies' JavaScript files into one single one.

A number of caveats apply:

  1. Strict mode: Many JavaScript files contain "use strict"; at the top of the file. This causes slightly different behavior in the JS engine. If the concatenated JS files have different expectations regarding strict mode, there could be problems.
  2. Hosted scripts: This script does not attempt to concatenate JS files that are hosted on CDNs. Instead, they're left in their original form. It's possible that files we do concatenate, either assume that a CDN-hosted script is loaded before it itself is, or, the opposite. combine_js has a parameter that lets you decide whether to put the combined script first or last, there's no way for us to decide automatically (assuming there's even a right answer).
  3. ES6 modules: We leave type="module" alone, because for ES6 modules the file boundarie
jcheng5 / app.R
Created April 5, 2024 18:34
crew + ExtendedTask while keeping track of who requested each result
run_task <- function(model, n, delay_secs) {
jcheng5 /
Created March 8, 2024 03:14
Color blindness helper in Shiny Express
# Live demo at
from PIL import Image
import nump
jcheng5 / app.R
Last active February 3, 2024 17:34
Using OAuth2 with Shiny
# WARNING: This sketch does not make proper use of the "state" parameter.
# Doing so usually involves using cookies, which can be done with the
# Rook package but I have not done that here. If you choose to use this
# approach in production, please check the state parameter properly!
APP_URL <- if (interactive()) {
# This might be useful for local development. If not, just hardcode APP_URL
# to the deployed URL that you'll provide a few lines below.
jcheng5 /
Last active February 2, 2024 16:24
Shiny for Python module for console you can write to
from shiny import App, reactive, render, ui, module
from shiny.session import Session
from contextlib import redirect_stdout, redirect_stderr
import asyncio
from shiny_console import Console, console_ui, console_server
# == Example usage =======================================
app_ui = ui.page_fluid(
jcheng5 / ggbrush.R
Last active September 9, 2023 23:55
# Call ggbrush with a ggplot2 object, and the dimensions which
# should be brushed (try "xy" for scatter, "x" for histogram).
# The plot will show in RStudio Viewer or your web browser, and
# any observations selected by the user will be returned.
ggbrush <- function(plotExpr, direction = c("xy", "x", "y")) {
# See below for definition of dialogPage function
jcheng5 /
Last active June 21, 2023 00:27
Debounce and throttle for Shiny for Python

Sketch of debounce/throttle decorators for Shiny for Python

Drop into your app directory to use in your own Shiny for Python app. See for an example of these decorators in action.

Why is this a gist instead of a PR? Because to implement this "properly" for Shiny for Python, this would need to be beefed up to include type annotations, support for async, and unit/integration tests, which would all be more effort than this has taken so far. (To be clear, we want to do all that, but in the meantime, here's this gist.)

jcheng5 / withConsoleRedirect.R
Created June 29, 2016 05:05
Someone at #useR2016 asked me if you can have Shiny execute code in observers/reactives but send the console output to the browser.
withConsoleRedirect <- function(containerId, expr) {
# Change type="output" to type="message" to catch stderr
# (messages, warnings, and errors) instead of stdout.
txt <- capture.output(results <- expr, type = "output")
if (length(txt) > 0) {
insertUI(paste0("#", containerId), where = "beforeEnd",
ui = paste0(txt, "\n", collapse = "")