Hello,
I am trying to create the following in R Shiny:
- Allow user to search a database using certain filters
- After clicking the button “Update,” the server returns n search results
- Use renderUI() to create n actionButtons with inputId = btnResult[i] (where i goes from 1 to n), one actionButton for each search result.
- Include observeEvent(input$btnResult[i]) that changes the reactive value of myMap to i when clicked.
- renderPlotly to plot a map based on the value of myMap().
I have completed steps 1, 2, and 5, but am having difficulty with steps 3 and 4.
My issue is that to my understanding, input values cannot be written in the format input$btnResult[i], and you also cannot write a single generalized observeEvent() function that for any potential value of i, can listen for input$btnResult[i] to be clicked and on being clicked set myMap(i). Instead, I think I have to write n copies of observeEvent() as shown in the example code below. This isn’t that bad for 4 results, but if the user might return 50 results, it feels clunky to repeat an observeEvent() block for each potential value of i. An example of what does work is shown below for n = 4.
library(shiny)
library(plotly)
data(iris)
iris
# example data (as a list because my database API call returns results in lists)
dfMap<- list()
dfMap[[1]] <- c(1,2,3)
dfMap[[2]] <- c(2,4,6)
dfMap[[3]] <- c(3,6,9)
dfMap[[4]] <- c(4,8,12)
ui <- fluidPage(
uiOutput("matchHistory"),
plotlyOutput("pltMap")
)
server <- function(input, output) {
myMap <- reactiveVal(0)
output$matchHistory <- renderUI ({
lstMatches <- list()
## now add all the matches to the list one by one
for (i in 1:4) {
lstMatches[[i]] <- tags$div(class="match",
### button indexed as btnMatch1, btnMatch2, etc.
actionButton(paste0("btnMatch", i), "Review")
)
}
lstMatches #return match list
})
observeEvent(input$btnMatch1, {
myMap(1)
})
observeEvent(input$btnMatch2, {
myMap(2)
})
observeEvent(input$btnMatch3, {
myMap(3)
})
observeEvent(input$btnMatch4, {
myMap(4)
})
output$pltMap <- renderPlotly({
if (myMap() > 0) {
plot_ly(x = 1:3, y = dfMap[[myMap()]], type = "bar")
}
})
}
shinyApp(ui = ui, server = server)
However, for larger values of n, this becomes cumbersome because I need to repeat observeEvent() for every single button. I am looking for something like
actionButton(paste0("btnMatch[", i, "]"), "Review")
and one single generalized observeEvent() a la
observeEvent(input$btnMatch[i], {
myMap(i)
})
But this kind of formatting is not allowed as HTML object IDs cannot be indexed or in an array. Is there some sort of function within R Shiny that would allow me to circumvent this?
I hope I explained my problem clearly and thank you for your time.