Introducing Shiny Apps in My Blog Posts

I love shiny apps written in R! They are an absolutely fantastic way to make your code immediately useful to others (and to increase productivity for yourself). This post is a quick test to see how easy it is to implement shiny apps on this website (which is written with blogdown in R).

I followed a simple description of the process i found online.

Here is the code I will use in blogdown to embed the app, which is published (at no cost) on shinyapps.io:

<iframe height="800" width="100%" frameborder="no" src="https://maxfus.shinyapps.io/Quotes/"> </iframe>

And here is the actual embedding of the shiny app, a tiny tool for adding/removing quotes from string lists that I’ve been meaning to make for a long time:

And finally, here is the code for the app (basically a quick regexp hack):

library(shiny)
library(shinyWidgets)
library(tidyverse)
library(rclipboard)

ui <- fluidPage(
  rclipboardSetup(),
  titlePanel("Quickly add and remove quotes"),
  
  sidebarLayout(
    
    sidebarPanel(
      textInput('string', 'String/List to modify', value='a,b,c,d', width='100%'),
      textInput('sep', 'Separator', width = '17%', value = ','),
      materialSwitch(
        inputId = 'ignorespace',
        label = 'Space after separator is not part of string',
        value = TRUE,
        status = 'primary',
        right = TRUE
      ),
      materialSwitch(
        inputId = 'spaceaftersep',
        label = 'Add space after separator when adding quotes',
        value = TRUE,
        status = 'primary',
        right = TRUE
      ),
      materialSwitch(
        inputId = 'removesallspace',
        label = 'Remove all spaces after separator when removing quotes',
        value = TRUE,
        status = 'primary',
        right = TRUE
      ),
      radioGroupButtons(
        'quotetype',
        'Choose Quotes',
        choices = c('single', 'double'),
        selected = 'single'
      ), hr(), 
      materialSwitch('swapsep', 'Swap separator', FALSE, 'primary', TRUE),
      conditionalPanel("input.swapsep", 
                       textInput('newsep', 'New separator', width = '17%'))
    ),
    mainPanel(
      tabsetPanel(
        tabPanel("Add",
          br(),HTML('<strong>Output:</strong>'),br(),br(),
          textOutput(outputId = 'converted'), br(),br(),
          conditionalPanel("input.string",hr(),
                           uiOutput("clip"),hr())),
        tabPanel("Remove",
                 br(), HTML('<strong>Output:</strong>'),br(),br(),
                 textOutput(outputId = 'converted2'), br(),br(),
                 conditionalPanel("input.string",
                                  uiOutput("clip2"),hr()))
                 ))))

server <- function(input, output) {
  string_out <- reactive({
    if (input$string != '') {
      q <- ifelse(input$quotetype == 'single', "'", '"')
      string <- ifelse(input$ignorespace, 
                       str_replace_all(input$string, paste0(input$sep, '  *'), input$sep), 
                       input$string)
      string <- str_replace_all(string, input$sep, paste0(q, input$sep, q))
      if (input$spaceaftersep) {
        string <- str_replace_all(string, input$sep, paste0(input$sep, " "))
      }
      string2 <- str_remove_all(input$string, ifelse(input$quotetype == 'single', "'", '"'))
      if (input$removesallspace) {
        string2 <- str_replace_all(string2, paste0(input$sep, '  *'), input$sep)
      }
      if (input$swapsep) {
        string <- str_replace_all(string, input$sep, input$newsep)
        string2 <- str_replace_all(string2, input$sep, input$newsep)
      }
      list(paste0(q, string, q), string2)
    }
  }
)
  
    output$converted <- renderText({ 
      string_out()[[1]]
      })
    
    output$converted2 <- renderText({ 
      string_out()[[2]]
    })
    
    output$clip <- renderUI({
      rclipButton("clipbtn", "Copy to clipboard", string_out()[[1]], icon("copy"))
    })
    
    output$clip2 <- renderUI({
      rclipButton("clipbtn", "Copy to clipboard", string_out()[[2]], icon("copy"))
    })
}

shinyApp(ui = ui, server = server)

Alright, seems to work well! I might use this blog section to deploy / announce more small apps.

Maximilian JLJ Fürst
Maximilian JLJ Fürst
Assistant Professor of Computational Protein Design

I research computational protein design and high-throughput protein engineering.

Related