I am looking for a way to choose from a given set of items (say the months of the year) a subset of items (say those months which I like) as well as (simultaneously) a single item (could be my birthday month). Depending on the choices, some more information needs to be printed (this might be the percentage of days which this month contributes to the overall favourite months). A datatable containing columns with
- all possible items (month names)
- checkboxes
- radiobuttons
- additional output
would be a technical realisation of this idea.
I have found working examples for each of checkboxes (entry of 2015-06-11) and radiobuttons (answer of 2016-08-12) separately, but I am unable to combine these. It seems to me that the underlying mechanism is different; but maybe I am simply lacking JS knowledge. The following code tries to include the radioButtons into the checkbox example; the checkboxes are still working, the radioButtons seem to be working but I can't access the actual choice :-(
library(shiny)
library(DT)
shinyApp(
ui = fluidPage(DT::dataTableOutput('x1'), verbatimTextOutput('x2'), verbatimTextOutput('sel')),
server = function(input, output) {
# create a character vector of shiny inputs
shinyInput = function(FUN, len, id, ...) {
inputs = character(len)
for (i in seq_len(len)) {
inputs[i] = as.character(FUN(paste0(id, i), label = NULL, ...))
}
inputs
}
# obtain the values of inputs
shinyValue = function(id, len) {
unlist(lapply(seq_len(len), function(i) {
value = input[[paste0(id, i)]]
if (is.null(value)) NA else value
}))
}
# a sample data frame
res = data.frame(
Month = month.abb,
Like = shinyInput(checkboxInput, 12, 'v2_', value = TRUE),
# v3 is constructed as in the radioButton matrix example
Birthday = sprintf('<input type="radio" name="%s" value="%s"/>', "rButton", 1:12),
Info = sample(LETTERS, 12, TRUE),
stringsAsFactors = FALSE
)
# render the table containing shiny inputs
output$x1 = DT::renderDataTable(
res, server = FALSE, escape = FALSE, selection = 'none', options = list(
dom = 't', paging = FALSE, ordering = FALSE,
# is the preDrawCallback argument needed? Seems to have no effect at all.
preDrawCallback = JS('function() { Shiny.unbindAll(this.api().table().node()); }'),
drawCallback = JS('function() { Shiny.bindAll(this.api().table().node()); } ')#,
# the following is from the radioButton matrix example, but doesn't work here
# callback = JS("table.rows().every(function(i, tab, row) {
# var $this = $(this.node());
# $this.attr('id', this.data()[0]);
# $this.addClass('shiny-input-radiogroup');
# });
# Shiny.unbindAll(table.table().node());
# Shiny.bindAll(table.table().node());")
)
)
# print the values of inputs
output$x2 = renderPrint({
data.frame(Like = shinyValue('v2_', 12))
})
output$sel = renderPrint({
# this is from the radioButton matrix example but doesn't work here
str(sapply("rButton", function(i) input[[i]]))
})
})
On the other hand I am not sure whether this will - when realised - make an intuitive, useful interface. I am also interested in advice regarding the structure of the user interface.