Using a URL to Pipe Information into a shiny application

Hi everyone,

I have a pretty complicated question, and if I need to move it/ change the category please let me know.

I am currently building a shiny dashboard to return results from a survey designed using REDCap. I have built the dashboard, and it communicates (when I run it locally) with the database using the REDCap API and the R package redcapAPI. I am moving towards trying to host this application somewhere (shinyapps.io?) and have a part that I cannot figure out.

Currently, my shiny application connects to the database (successfully!) using the following code snippet

library(redcapAPI)
#establish connection to the API
 project <- redcapConnection(url, token)

I then pull the information I want using this function:

#extract only the records from the appropriate subject by variable subject_id into a data frame
 data <- exportRecords(project,records = c(subject_id))

Currently, I have to hard code the variable subject_id so that I can change which set of records I am pulling in.

The REDCap program, allows me to redirect a user to a custom URL upon completion of the survey, and I can pipe a variable (subject_id) into the URL. So I could have something like this:

https://www.EXAMPLE.extension?subjectID=[redcap_subject_id]

My question is if it is possible to have all of the information needed to launch my application with the appropriate subject ID stored inside of the URL? Are there any tips or resources you can think of that would make this work? Or am I attempting the impossible?

Any input is much appreciated.

Chris

I believe you can, take a look at this related thread for a simple example

If you get stuck implementing it, come back here with a reproducible example of your issue.

1 Like

Thank you very much! I will do just this, and come back if anything goes awry!

Hi andresrcs,

I tested this, and the issue I kept having was with the error message pasted below as well as a message that says "disconnected to server Reload" on the actual page.

Warning: Error in .getReactiveEnvironment()$currentContext: Operation not allowed without an active reactive context. (You tried to do something that can only be done from inside a reactive expression or observer.)
[shinyapps]:   65: stop
[shinyapps]:   64: .getReactiveEnvironment()$currentContext
[shinyapps]:   63: getCurrentContext
[shinyapps]:   62: .subset2(x, "impl")$get
[shinyapps]:   61: $.reactivevalues
[shinyapps]:   Error in .getReactiveEnvironment()$currentContext() : 
[shinyapps]:   59: server [/srv/connect/apps/shiny_004/app.R#76]
[shinyapps]:   Operation not allowed without an active reactive context. (You tried to do something that can only be done from inside a reactive expression or observer.)

I believe the issue is that I am not treating the information being read in from the session$clientData$url_search as a reactive value.

Pasted below is some of the server code. I wonder if you might suggest how to load this data table in a way that treats the variable as reactive? I have tried assigning it to reactiveValues(), but that has not worked.

server <- function(input, output, session) {
  #read the information from the URL 
  values <- reactiveValues(id = session$clientData$url_search)


  #Establish connection to API
  project <- redcapConnection(url,
                              token)#token will be placed here
  
   #export only records associated with the subject Id passed to records
  graph_data <- exportRecords(project,records = c(values$id)) %>%
    #select only the fields being assessed
    select('smell_cosmetics_intensity',
           'smell_spice_intensity',
           'smell_fruit_intensity',
           'smell_other_intensity',
           'nasalirritation_intensity',
           'taste_bitter_intensity',
           'taste_salt_intensity',
           'taste_sour_intensity',
           'taste_sweet_intensity')
  #transmute the table to generate a column for week and the averaged smell and taste values
  data <-  transmute(graph_data,
                      week = 0:(nrow(graph_data)-1),
                      smell = ((smell_cosmetics_intensity + smell_spice_intensity + smell_fruit_intensity + smell_other_intensity) / 4),
                      smell_2 = nasalirritation_intensity, 
                      taste = ((taste_bitter_intensity + taste_salt_intensity + taste_sour_intensity + taste_sweet_intensity)/4), 
                      taste_2 = nasalirritation_intensity)
  
  #Generate the oral summary graph
  output$oral_graph <- renderPlot({
    #this is the R code used to generate the Oral graph
    oral_graph <- ggplot(data, aes(x = week)) +
      geom_line(aes(y = taste), color = "green") +
      geom_line(aes(y = taste_2), color = "blue") +
      geom_point(aes(x = week, y = taste)) +
      geom_point(aes(x = week, y = taste_2)) +
      xlab("Time (weeks)") +
      ylab("Response to Stimuli") +
      theme_classic() +
      theme(text = element_text(size = 16))
    #return statement
    oral_graph
  })

To help us help you, could you please prepare a minimal reproducible example (reprex) illustrating your issue? Please have a look at this resources, to see how to create one for a shiny app

1 Like

Apologies. Let me read this and try to convert to a repex! Thank you

1 Like

Thanks for your help. I tried to create a simple repex, but all examples work fine when i execute them. I am unable to come up with a way to represent the issue as a repex without disclosing the token to my API, as I am quite sure the issue arises from piping the value from session$clientData$url_search into the data frame as illustrated in the code snippet I showed above.

Thank your for your assistance anyway, I will elaborate on the solution if I am able to solve it myself.

Chris

Andresrcs,

I am still having a lot of trouble accomplishing my goals. I have tried to make a simple repex that generates the same error. I have pasted it below. I believe the issue is that I am attempting to load the session$clientData$url_search variable into a datatable in the server function, and it needs to be made "reactive". I do not understand how to accomplish this.

library(shiny)

x_1 <- c(1, 5, 16, 71, 41, 71, 38)
x_2 <- c(12, 23, 88, 74, 62, 63, 34)
y_1 <- c(1, 2, 3, 4, 5, 6, 7)

ui <- fluidPage(
  titlePanel("test_1"),
  
  sidebarLayout(
    mainPanel(
      plotOutput("plot_1")
    ),
    
    mainPanel(
      plotOutput("plot_2")
    )
  )
)

server <- function(input, output, session) {
  # Here you read the URL parameter from session$clientData$url_search
  observe({
    query <- parseQueryString(session$clientData$url_search)
    subject_id <- query[["id"]]
  })
  
  data <- data.frame(input$id, x_2, y_1)%>%
    select(x_1, y_1)
  #Generate the oral summary graph
  output$plot_1 <- renderPlot({
    #this is the R code used to generate the Oral graph
    plot_1 <- ggplot(data, aes(x = input$id)) +
      geom_line(aes(y = y_1), color = "green") +
      theme_classic() +
      theme(text = element_text(size = 16))
    #return statement
    plot_1
  })
}

# Run the application 
shinyApp(ui = ui, server = server)

Can you check your reprex? there is no input@id defined in your UI function and you are not using the URL parameter (subject_id) anywhere in your code.

1 Like

Thank you for catching that. I am struggling to make the repex, as the true version uses code to generate the table from the API. I believe that this version is a better representation.

library(shiny)

x_1 <- c(1, 5, 16, 71, 41, 71, 38)
x_2 <- c(12, 23, 88, 74, 62, 63, 34)
y_1 <- c(1, 2, 3, 4, 5, 6, 7)

ui <- fluidPage(
  titlePanel("test_1"),
  
  sidebarLayout(
    mainPanel(
      plotOutput("plot_1")
    ),
    
    mainPanel(
      plotOutput("plot_2")
    )
  )
)

server <- function(input, output, session) {
  # Here you read the URL parameter from session$clientData$url_search
  observe({
    query <- parseQueryString(session$clientData$url_search)
    subject_id <- query[["id"]]
  })
  
  data <- data.frame(x_1, x_2, y_1)%>%
    select(input$subject_id, y_1)
  #Generate the oral summary graph
  output$plot_1 <- renderPlot({
    #this is the R code used to generate the Oral graph
    plot_1 <- ggplot(data, aes(x = input$subject_id)) +
      geom_line(aes(y = y_1), color = "green") +
      theme_classic() +
      theme(text = element_text(size = 16))
    #return statement
    plot_1
  })
}

# Run the application 
shinyApp(ui = ui, server = server)

Check again, you are defining the main panel twice and still referencing an unexisting UI input, subject_id is not a UI input, so you can't reference it that way.

I do not think this repex will be of use then. am not sure if this is more informative, but here is the actual code I am hoping to fix. The issue is line 77 where I attempt to pass subject_id into exportRecords() as an int.

You need to access the url parameter inside a reactive function, this is the simplest example I can come up with.

library(shiny)

ui <- fluidPage(
  titlePanel("test_1"),
    mainPanel(
      textOutput("text")
  )
)

server <- function(input, output, session) {
  
  url_parameters <- reactiveValues()
  
  observe({
    query <- parseQueryString(session$clientData$url_search)
    url_parameters$subject_id <- query[["id"]]
  })
  
  output$text <- renderText({
      paste("the value of the id parameter is:", url_parameters$subject_id)
  })
}

shinyApp(ui = ui, server = server)

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.