Skip to content

Instantly share code, notes, and snippets.

View jcheng5's full-sized avatar

Joe Cheng jcheng5

View GitHub Profile
@jcheng5
jcheng5 / README.md
Last active November 22, 2023 16:23
Accepting POST requests from Shiny
View README.md

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:

library(shiny)
@jcheng5
jcheng5 / ggbrush.R
Last active September 9, 2023 23:55
ggbrush
View ggbrush.R
library(ggplot2)
library(shiny)
# 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
jcheng5 / README.md
Last active June 21, 2023 00:27
Debounce and throttle for Shiny for Python
View README.md

Sketch of debounce/throttle decorators for Shiny for Python

Drop ratelimit.py into your app directory to use in your own Shiny for Python app. See app.py 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
jcheng5 / app.R
Last active May 22, 2023 22:46
Using OAuth2 with Shiny
View app.R
library(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
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.
View withConsoleRedirect.R
library(shiny)
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 = "")
)
@jcheng5
jcheng5 / README.md
Last active December 15, 2022 16:01
Using arbitrary Leaflet plugins with Leaflet for R
View README.md

Using arbitrary Leaflet JS plugins with Leaflet for R

The Leaflet JS mapping library has lots of plugins available. The Leaflet package for R provides direct support for some, but far from all, of these plugins, by providing R functions for invoking the plugins.

If you as an R user find yourself wanting to use a Leaflet plugin that isn't directly supported in the R package, you can use the technique shown here to load the plugin yourself and invoke it using JS code.

@jcheng5
jcheng5 / global.R
Last active November 30, 2022 02:01 — forked from dgrapov/global.R
View global.R
#initialize
library(datasets)
library(ggplot2)
#helper function (convert vector to named list)
namel<-function (vec){
tmp<-as.list(vec)
names(tmp)<-as.character(unlist(vec))
tmp
}
@jcheng5
jcheng5 / filters.R
Last active September 29, 2022 13:08
View filters.R
library(shiny)
columnFilterUI <- function(id) {
ns <- NS(id)
uiOutput(ns("filter_container"))
}
columnFilter <- function(input, output, session, df, col_num, choice_filter) {
# This renders a selectInput and only re-renders when the selected data
# frame changes. (i.e. it doesn't re-render when filters change state.)
@jcheng5
jcheng5 / create_forked_task.R
Last active August 3, 2022 17:11
Concurrent, forked, cancellable tasks in Shiny
View create_forked_task.R
library(shiny)
# Also uses parallel, shinyjs, tools
# Create a long-running task, executed in a forked process. (Doesn't work on Windows)
#
# The return value is a promise-like object with three
# methods:
# - completed(): FALSE initially, then TRUE if the task succeeds,
# fails, or is cancelled. Reactive, so when the state changes
# any reactive readers will invalidate.
@jcheng5
jcheng5 / server.R
Created November 10, 2012 08:13
Shiny file upload demo
View server.R
shinyServer(function(input, output) {
output$filetable <- reactiveTable(function() {
if (is.null(input$files)) {
# User has not uploaded a file yet
return(NULL)
}
input$files
})
})