Basic Shiny Reactivity: Download User-designated JSON file in Shiny

Viewed 65

I have an AWS bucket with a bunch of dynamically generated JSON files. When a file is generated it gets a "slug".

I'd like to be able to copy that slug (from an outside website) and enter it in a Shiny textInput box, then add the rest of the URL to the slug, and download the designated file as an R object. (I use jsonlite::fromJSON here).

The code below works, and it generates the correct string and puts it into a box in the ui side. But I can't figure out how to use that output variable on the server side. It is hard-coding the "slug". I want to use the slug from the ui textInput.

library(tidyverse)
library(igraph)
library(jsonlite)
library(circlize)
library(chorddiag)
library(plotly)

library(shiny)
library(shinydashboard)
library(shinyWidgets)
library(shinyjs)


ui <- dashboardPage(
  dashboardHeader(title = ""),
  dashboardSidebar(
    
    textInput("slug","Discovery ID",placeholder = "N79og8K"),
    fluidRow(box(textOutput("URL")))
  )
)

server <- function(input, output) {

#  raw_data_URL <- "https://XXX.s3.us-west-1.amazonaws.com"
#  raw_data_suffix <- ".json"
#
#  full_URL <- eventReactive(input$submit, {
#    paste0(raw_data_URL,"/",input$slug,raw_data_suffix)
#  })

#  output$URL <- renderPrint(full_URL())

  data <- fromJSON(paste0(raw_data_URL,"/","N79og8K",raw_data_suffix))
    
  )
}

I've tried all sorts of things with reactive objects, and haven't gotten anything to work.

Also, the commented out text does work too: it populates the box with the right string on "submit". But I can't get the server to go to the resulting file URL.

Can I use the output variable in my server app?

2 Answers

The following app will prepare the URL, fetch it, and then modify it in the server. It will print the output at each step.

library(tidyverse)
library(shiny)
library(jsonlite)

ui <- fluidPage(
  textInput("slug","Type in Name",value = "charlie"),
  actionButton("submit", "Submit"),
  textOutput("URL"),
  textOutput("raw_JSON"),
  textOutput("modified_JSON")
)

server <- function(input, output) {
  
  raw_data_URL <- "https://api.genderize.io/?name="
  
  full_URL <- eventReactive(input$submit, {
    paste0(raw_data_URL,input$slug)
  })
  
  output$URL <- renderPrint(full_URL())
  
  full_JSON <- reactive({
    fromJSON(full_URL())
  })
  
  output$raw_JSON <- renderPrint(full_JSON())
  
  JSON <- reactive({
    full_JSON()$probability
  })
  
  output$modified_JSON <- renderPrint(JSON())
}

shinyApp(ui = ui, server = server)

I removed the shinydashboard package to make the solution more minimal. Not every Shiny developer has or knows it.

The key point is that when you want to use something reactive, you have to treat it like a function and put () after it, like I did for full_URL(), full_JSON() and JSON() above. Also, you can only use reactive objects inside of other reactives like reactive() and renderPrint().

Here's a minimal reprex of what actually ended up working

library(shiny)
library(shinydashboard)
library(shinyWidgets)
library(tidyverse)
library(jsonlite)
library(igraph)
library(plotly)
library(chorddiag)


  ui = dashboardPage(
    dashboardHeader(),
    dashboardSidebar(fluidRow(textInput("slug", "Discovery ID",value = "VJPEqQB")),
                     actionButton("submit", "Submit")),
    dashboardBody()
),

server = function(input, output, session) {
  
  raw_data_URL <- "https://XXX-bucket.s3.us-west-1.amazonaws.com"
  raw_data_suffix <- "_graph.json"
  
  saveData <- function(data) {
    set.seed(1)
    data <- fromJSON(data)
    
  }
  
  # Construct the URL
  getURL <- reactive({
    data <- paste0(raw_data_URL,"/",input$slug,raw_data_suffix)
    data
  })
  
  # When the Submit button is clicked:
  observeEvent(input$submit, {
    saveData(getURL())
  })
  
  # Show Outputs (omitted from MRE)
  
  # Not Used:
  output$graph <- renderPlot({
    input$submit
    plot(net) # net is a graph object derived from `data`
  })
  
}
)
Related