4
votes

I would like to dynamically create a series of input widgets to use in each row of data table. I am successfully able to display such a list of inputs in the table, however I'm having trouble accessing the value of these dynamic inputs.

ui.R

library(shiny)

ui <- fluidPage(

  fluidRow(
    radioButtons('original','Normal Radio Button',c('1','2','3','4','5')),
    DT::dataTableOutput("table")
  )
)

server.R

library(DT)

multipleRadio <- function(FUN, id_nums, id_base, label, choices, ...) {

  inputs <- 1:length(id_nums)
  for (i in 1:length(inputs)) {
    inputs[i] <- as.character(FUN(paste0(id_base, id_nums[i]),label, choices, ...))
  }

  return(inputs)
}

radio_inputs <- multipleRadio(radioButtons,
                       as.character(1:3),
                       'input_',
                       'Radio Button',
                       c('1','2','3','4','5'),
                       inline = TRUE)

output_table <- data.frame(id = c(1,2,3),
                           name=c('Item 1','Item 2','Item 3'),
                           select = radio_inputs)


server <- function(input, output, session) {

  observe({
    print(paste('original: ',input$original))
    print(paste('input 1: ',input$input_1))
    print(paste('input 2: ',input$input_2))
    print(paste('input 3: ',input$input_3))
 })

  output$table <- renderDataTable({   
    datatable(output_table,rownames= FALSE,escape = FALSE,selection='single',
            options = list(paging = FALSE,ordering=FALSE,searching=FALSE))
  })
}

I define a function which generates multiple radioButton inputs and converts them into their HTML representation using as.character. This generates a series of inputs whose ids are "input_1", "input_2", and "input_3." I fill a column of the output table with the radio inputs. The display of the radioButtons works as expected. I see one in each row. However, input$input_1,input$input_2, and input$input_3 don't seem to exist and there is no response to clicking on these buttons. Any tips on what's going wrong here would be greatly appreciated!

Edit:

I found a solution here: http://www.stackoverflow.red/questions/32993257/shiny-datatables-with-interactive-elements

Using the Shiny.bindAll function when rendering the datatable appears to convert the HTML inputs into Shiny input objects.

output$table <- renderDataTable({ 
    datatable(output_table,rownames= FALSE,escape = FALSE,selection='single',
              options = list(paging = FALSE,ordering=FALSE,searching=FALSE, 
                             preDrawCallback=JS('function() { Shiny.unbindAll(this.api().table().node()); }'),
                             drawCallback=JS('function() { Shiny.bindAll(this.api().table().node()); } ')))
})
1
The key is to create the dynamic inputs using renderUI. See stackoverflow.com/questions/36094718/r-shiny-dynamic-input/… for a question that I previously answered.Xiongbing Jin
Thanks, @warmoverflow. Once I generate the inputs using renderUI how do I fill the data table with them?Emily
You just read the value like input$input1 etcXiongbing Jin
@warmoverflow Ah I want the widget itself to be displayed inside the data table, not the value of the input. Sorry if I was unclear.Emily
Sorry I misunderstood your question. I suspect that as both DT and shiny inputs use javascript, nesting one inside the other breaks something.Xiongbing Jin

1 Answers

0
votes

A correct shiny input object is a shiny.tag object, which you cannot put into a data.frame. If you do so, you'll get the following error message:

Error in as.data.frame.default(x[[i]], optional = TRUE, stringsAsFactors = stringsAsFactors) : cannot coerce class ""shiny.tag"" to a data.frame

In your example, the radio_inputs object you get is in fact a list of character, which is pure HTML code. Thus you still get the UI, but they no longer work as shiny inputs.

I guess the only way is to use a pure HTML table if you want radio buttons or any other shiny input objects inside a table.