First, you have to use these options preDrawCallback
and drawCallback
, otherwise Shiny is not aware of the selectors:
output[["foo"]] <- renderDT(
data, escape = FALSE, selection = 'none', server = FALSE,
options = list(
dom = 't',
paging = FALSE,
ordering = FALSE,
preDrawCallback = JS(
"function() { Shiny.unbindAll(this.api().table().node()); }"
),
drawCallback = JS(
"function() { Shiny.bindAll(this.api().table().node()); }"
)
)
)
Now, you can use two reactive values to store the row and the species:
row <- reactiveVal()
species <- reactiveVal()
And then, define an observer for each row:
lapply(1:nrow(data), function(i){
selector <- paste0("change", i)
observeEvent(input[[selector]], {
row(i)
species(input[[selector]])
})
})
Full app:
library(shiny)
library(DT)
ui <- fluidPage(
br(),
DTOutput('foo'),
br(),
wellPanel(
textOutput("text")
)
)
server <- function(input, output, session) {
data <- head(iris, 5)
data$species_selector <- vapply(1:nrow(data), function(i){
as.character(selectInput(
paste0("change", i),
label = paste0("change", i),
choices = unique(iris$Species),
width = "100px"
))
}, character(1))
output[["foo"]] <- renderDT(
data, escape = FALSE, selection = 'none', server = FALSE,
options = list(
dom = 't',
paging = FALSE,
ordering = FALSE,
preDrawCallback = JS(
"function() { Shiny.unbindAll(this.api().table().node()); }"
),
drawCallback = JS(
"function() { Shiny.bindAll(this.api().table().node()); }"
)
)
)
row <- reactiveVal()
species <- reactiveVal()
lapply(1:nrow(data), function(i){
selector <- paste0("change", i)
observeEvent(input[[selector]], {
row(i)
species(input[[selector]])
})
})
output[["text"]] <- renderText({
sprintf("Row %d --- Species %s", row(), species())
})
}
shinyApp(ui, server)