Shinylive

Run shiny apps in the browser

Author

Roy Francis

Published

September 6, 2024

1 Setup

The shinylive R package is required locally when building the document.

install.packages("shinylive")

For quarto, add quarto filter shinylive.

quarto add quarto-ext/shinylive

Add to filters in yaml:

filters:
  - shinylive

R code block with shiny component must use language shinylive-r rather than r. Packages are installed using webr. Chunk option #| standalone: true must be defined.

Here is the general structure of a shinylive chunk:

```{shinylive-r}
#| standalone: true

webr::install("ggplot2")
library(ggplot2)

ui <- fluidPage()
server <- function(input, output, session) {}
shinyApp(ui, server)
```

2 App in a chunk

Note

The app can take a while to load. For full code, use code-tools, ie; click ‘Code’ at the top.

#| standalone: true
#| viewerHeight: 450

webr::install(c("ggplot2", "bslib", "palmerpenguins", "htmltools"))

library(htmltools)
library(bslib)
library(ggplot2)
library(palmerpenguins)
data("penguins")

pdata <- na.omit(penguins)
pc <- prcomp(pdata[,c("bill_length_mm", "bill_depth_mm", "flipper_length_mm", "body_mass_g")], center = TRUE, scale. = TRUE)
dfr <- cbind(pdata,as.data.frame(pc$x))

ui <- page_sidebar(
  sidebar = sidebar(
    selectInput("x",
      label = "X axis",
      choices = c("PC1","PC2","PC3","PC4"),
      selected = "PC1"
    ),

    selectInput("y",
      label = "Y axis",
      choices = c("PC1","PC2","PC3","PC4"),
      selected = "PC2"
    ),
    selectInput("v",
      label = "Color",
      choices = c("species", "island", "sex"),
      selected = "cut"
    )
  ),
  imageOutput("plot", height = "350px")
)

server <- function(input, output, session) {
  
  output$plot <- renderImage({
    x <- input$x
    y <- input$y
    v <- input$v
    
    p <- ggplot(dfr, aes(x = !!sym(x), y = !!sym(y), col = !!sym(v))) +
      geom_point() +
      theme_bw() + 
      theme(legend.position = "top")

    file <- htmltools::capturePlot(
      print(p), 
      tempfile(fileext = ".svg"),
      grDevices::svg,
      width = 4, 
      height = 4
    )
    
    list(src = file)
  }, deleteFile = TRUE)
}

app <- shinyApp(ui = ui, server = server)

3 More options

Adding #| components: [editor, viewer] displays code editor and viewer side by side.

#| standalone: true
#| components: [editor, viewer]

shinyApp(
  ui=fluidPage(
    sliderInput("value", label="Value", min=1, max=50, step=1, value=2),
    textOutput("out")
  ),
  server=function(input, output, session) {
    output$out <- renderText(paste0("Squared: ",input$value^2))
  }
)

Adding #| layout: vertical displays editor and viewer vertically.

#| standalone: true
#| components: [editor, viewer]
#| layout: vertical

shinyApp(
  ui=fluidPage(
    sliderInput("value", label="Value", min=1, max=50, step=1, value=2),
    textOutput("out")
  ),
  server=function(input, output, session) {
    output$out <- renderText(paste0("Squared: ",input$value^2))
  }
)

4 Multi-file app

The app code can be split into separate files by specifying ## file: filename.r.

```{shinylive-r}
#| standalone: true
#| components: [editor, viewer]

## file: ui.r
ui <- fluidPage(
  sliderInput("value", label="Value", min=1, max=50, step=1, value=2),
  textOutput("out")
)

## file: server.r
server <- function(input, output, session) {
  output$out <- renderText(paste0("Squared: ",input$value^2))
}
```
#| standalone: true
#| components: [editor, viewer]

## file: ui.r
ui <- fluidPage(
  sliderInput("value", label="Value", min=1, max=50, step=1, value=2),
  textOutput("out")
)

## file: server.r
server <- function(input, output, session) {
  output$out <- renderText(paste0("Squared: ",input$value^2))
}

shinyApp(ui=ui,server=server)

5 Acknowledgements